原型链 及 new 到底做了什么

188 阅读1分钟

构造函数名一般为大写字母开头,与new运算符一起使用来实例化对象。

// 构造函数
function Person() { 
  this.name = 'Denise'
}
// 创建对象(实例化)
var p = new Person()

// 打印出来看看
console.log(Person.prototype)
console.log(p)

什么是原型呢?

构造函数在创建的过程中,系统自动创建出来与构造函数相关联的一个空的对象。可以由构造函数 .prototype 来访问到。如上述代码,在实例化对象p的过程中,系统就自动创建出了构造函数的原型 Person.prototype

5797422-9ab2f92b5227fc00.png

每个对象的 __proto__ 属性指向自身构造函数的prototype。如上述代码,对象p的 __proto__ 指向 Person.prototypeconstructor属性是原型对象Person.prototype 的属性,指向这个原型对象所对应的构造函数,即Person

5797422-2b87596356db0b22.webp

关键在于 __proto__ ,那 __proto__ 到底是什么呢?

简单来说,每个对象都会有一个 __proto__ 属性,当我们访问一个对象的属性时,如果这个对象本身不存在这个属性,那么它就会去 __proto__ 里找这个属性,这个 __proto__ 又会有自己的 __proto__ ,于是就这样一直找下去,这就是所谓的原型链。

在上面这个例子中的p对象的原型链结构图如下: p -----> Person.prototype (p.__proto__) -----> Object.prototype (p.__proto__.__proto__) -----> null

那么,new 到底做了什么?

// 构造函数
function Person() { 
  this.name = 'Denise'
}
// 创建对象(实例化)
var p = new Person()

// 模拟推导过程 --> 
var p = {};   
p.__proto__ =  Person.prototype;  
Person.call(p); 

1.创建一个空对象 p
2.把这个空对象 p 的属性 __proto__ 指向函数 Personprototype
3.将构造函数 Person 的作用域赋给新对象 p,即 this 指向了 p
4.执行Person 中的代码,为p添加属性 name
5.返回新对象