使用构造函数方式,主要是为了创建类和实例的,也就是基于面向对象编程思想来实现一些需求的处理.
在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的实例,而是变为手动返回的对象了