解析构造函数的底层原理

695 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情

背景

面向对象里面的三大特征分别是封装、继承、多态,而封装时我们常用的三种方式分别是:

  • 直接声明:var obj={属性名:'',方法名:function(){...}} ;
  • new Object(), var obj=new Object();obj.属性名='';obj.方法名=function(){...};
  • 构造函数 前两种方式,有个问题是:每次只能创建一个对象,如果要创建的对象很多的话,就会很麻烦,出现大量的重复代码,因此,第三种方式就解决的这个问题,那就是构造函数。
    解决:
    只要想反复创建多个相同结构,只是内容(功能,元素值)不同的对象时,都要使用构造函数

什么是构造函数

描述同一类型的所有对象的统一结构的函数

为什么使用构造函数

代码重用构造函数为了重用对象的结构

如何使用构造函数

2步:

  • 定义构造函数
var 类型名=function(形参1,形参2,...){
 //将来要加入新对象中规定的属性
 this.属性名=形参1,  
 this.xxx=xxx,
 this.方法名=function(){
 ...this.属性名...
 }
}
  • 使用构造函数反复创建多个相同结构的对象
var 对象名=new 类型名(实参1,实参2,...);

到这里,new暂时干了2件事(这里不代表new只能代表这2件事):

  • 创建一个指定类型的新对象;
  • 把实参传到构造函数的形参里面去;

构造函数的底层原理

表面原理

表面原理:实参传给构造函数的形参,形参传给属性值,属性值通过this交给新对象。

var 类型名=function(形参1,形参2,...){
 //将来要加入新对象中规定的属性
 this.属性名=形参1,  
 this.xxx=xxx,
 this.方法名=function(){
 ...this.属性名...
 }
}
var 对象名=new 类型名(实参1,实参2,...);

底层原理到底是什么呢?

var obj=function(name,age){
    this.name=name,
        this.age=age,
        this.say=function(){
            console.log(this.name);
        }
}
var obj1=new obj('静静',18);

这段代码底层是这样运行的:

  • 在window里创建全局变量obj,在内存中保存了全局变量obj的地址,并且,new Function(),因为看到小写function就相当于创建了一个new Function(),并且已经形成了自己的作用域链,目前有两个作用域,第一个是自己,但是目前为空,因为还没有调用,因此自己还没有形成作用域,第二个是window
  • 执行最后一行代码,var obj1=new obj('静静',18),先执行var obj1, 先把地址保存下来,在window创建了一个全局变量obj1,值是undefined,因为此行代码还没有执行完,因此,值暂时没有;再接着执行new obj('静静',18);,先执行new,new在这里一共做了3件事(不代表new一共只能做这3件事,这里不包含所有情况哦):
  1. 先创建一个新对象
  2. 调用构造函数,new 干了一件事,就是把构造函数里面的this替换成new刚创建的新对象,从this.属性值->新对象.属性值,在构造函数内通过强制赋值方式,为新对象添加规定的属性和方法
  3. 返回新对象的地址,保存在内存中
  • 接着执行new obj('静静',18);,调用构造函数,执行函数三部曲来啦:
    1)先备料,创建一个临时的构造函数的作用域,这里构造函数的作用域就不为空了,有了自己的地址,创建局部变量,这里的形参name,age是来自于调用构造函数传进来的实参值,属于构造函数的局部变量
    2)根据菜谱做菜,也就是说按照程序执行代码,构造函数里面有this ,这里的所有this被new强制替换成新对象,也就是说this指向的是新对象obj1,这时,构造函数里面的所有带this的属性和方法都强制性的被赋值在新对象obj1里。这里的say方法faunction又创建一个小函数,function->new Function(),并不存在对象内部,只是把地址放在在对象内部。
    3)收拾厨房构造函数调用完毕,就清除构造函数的临时作用域以及局部变量
    为什么构造函数里面有那么多this,并且需要用new去调用构造函数?
    其实,构造函数除过内部的this外,就是个普通的函数,构造函数内部的固定搭配this,和new 对象名()的固定搭配new搭建成一个桥梁,形成一个吸铁石,让构造函数里的属性和方法走到新对象里面去