JS中构造函数设计模式(constructor)

使用构造函数方式,主要是为了创建类和实例的,也就是基于面向对象编程思想来实现一些需求的处理.


在JS中,当我们使用 new xxx() 执行函数的时候, 此时的函数就不是普通的函数了,而是变为一个类,返回的结果叫做当前的类的实例,我们这种 new xxx 执行的方式称之为 构造函数设计模式

function fn(){
    ...
}
var f=new fn();//=>fn是一个类,f是当前这个类的一个实例 “构造函数设计模式” (我们一般都会把类名第一个字母大写)


普通函数执行 VS 构造函数执行

普通函数执行 

1、开辟一个新的私有作用域 

2、形参赋值 

3、变量提升 

4、代码自上而下执行(return后面的值就是当前函数返回的结果) 

5、栈内存释放或者不释放问题

function fn(num){
    this.num=num;//=>this:window 给全局对象增加一个num的属性名,属性值是10
    var total=null;
    total+=num;
    return total;
}
var f=fn(10);//=>f:10


构造函数执行 

1、首先和普通函数执行一样,也需要开辟一个新的私有作用域 

2、在私有作用域中完成类似于普通函数的操作:形参赋值以及变量提升 

3、在代码自上而下执行之前,构造函数有属于自己比较特殊的操作:浏览器会在当前的作用域中默认创建一个对象数据类型的值,并且会让当前函数中的this指向创建的这个对象 

4、像普通函数一样,代码自上而下执行:this.xxx=xxx这里操作都是在给创建的这个对象增加属性名和属性值 

5、代码执行完成后,即时函数中没有写return,在构造函数模式中:浏览器会默认的把创建的对象返回到函数的外面


构造函数执行,即具备普通函数执行的一面,也同时具备自己独有的一些操作; 

在构造函数执行期间,浏览器默认创建的对象(也就是函数体中的this)就是当前这个类的一个实例,浏览器会把默认创建的实例返回,所以我们说:new Fn()执行,Fn是一个类,返回的结果是Fn这个类的一个实例

function Fn(num){
    //=>在构造函数模式中,方法体中出现的THIS是当前类的一个实例(this.xxx=xxx都是在给当前实例增加一些私有的属性)
    this.num=num;
}
var f = new Fn(10);


深入理解构造函数执行的步骤

>> 当构造函数或者类,执行的时候不需要传递任何的实参值,此时我们是否加小括号就不重要了(不传递实参的情况下,小括号可以省略)

>> 构造函数执行,同时具备了普通函数执行的一面,也有自己特殊的一面,但是和实例相关的,只有自己特殊的一面才相关(也就是 this.xxx=xxx才相当于给当前实例增加的私有属性),函数体中出现的私有变量,和实例都没有直接的关系

>> 通过类创建出来的每一个实例都是单独的个体(单独的堆内存空间),实例和实例之间是不相同并且独立互不影响的(市面上部分开发把这种模式叫做单例模式,这种说法是错的,JS中的这种模式叫做构造函数设计模式)

>> 在构造函数体中,通过this.xxx=xxx给实例设置的属性都是当前实例的私有属性

function Fn(){
    var num=100;
    this.name='我的兜兜有糖';
    this.sum=function(){};
}
var f1 = new Fn();
var f2 = new Fn;

//=>私有变量和实例没关系
console.log(f1.num);//=>undefined
console.log(f1.name);//=>'我的兜兜有糖'

//=>不同实例是不同的空间地址
console.log(f1===f2);//=>false
console.log(f1.sum===f2.sum);//=>false


当构造函数体中我们自己手动的设置了RETURN(默认返回的是实例:对象类型值), RETURN 的是一个基本类型值,对最后返回的实例没有任何的影响,但是如果返回的是引用数据类型的值,会把默认返回的实例替换掉;

function Fn(){
    this.name='我的兜兜有糖';
    return 10;
}
var f = new Fn();//=>f依然是当前类的一个实例

function Fn(){
    this.name='我的兜兜有糖';
    return {name:'xxx'};
}
var f = new Fn();//=>f不再是Fn的实例,而是变为手动返回的对象了


2.png