JavaScript 对象体系是基于构造函数和原型链的。继承不通过类,而是通过原型对象实现,原型对象的所有属性和方法,都能被实例对象共享。
构造函数(constructor)
在 JS 中想要生成可重用、可继承的对象就要使用构造函数:
- 函数体内部使用了
this
关键字,代表了所要生成的对象实例。 - 生成实例对象的时候,必须使用
new
命令。
new
命令的原理:
- 创建一个新的空对象。
- 新对象的
__proto__
指向构造函数的prototype
。 - 新对象赋值给构造函数内部的 this 上下文,并开始执行构造函数。
- 如果构造函数没有显示返回对象,默认返回 this(即生成的实例)。
原型和原型链(__proto__、prototype)
- 每个构造函数都有一个
prototype
属性指向原型对象,用来存放共有属性和方法的地址。 - 每个实例对象都有一个
__proto__
属性指向构造函数的原型对象。
一个实例对象的原型就是它的构造函数的原型对象,原型对象的所有属性和方法,都能被实例对象共享,不仅节省了内存,还体现了实例对象之间的联系。
let arr = [1,2,3,4]
arr.__proto__ === Array.prototype //true
Array.prototype.__proto__ === Object.prototype //true
Object.prototype.__proto__ === null //true
所有对象都有一个__proto__
属性指向一个原型对象,从原型到原型的原型……这样就形成了一个“原型链”(prototype chain)。原型链的尽头就是null,null没有任何属性和方法,也没有自己的原型。
arr ---> Array.prototype ---> Object.prototype ---> null
Object
和Function
的关系有点绕:
Object的构造函数是Function。
Object.__proto__ === Function.prototype
Function的构造函数是它自己。
Function.__proto__ === Function.prototype
Function.prototype的构造函数是Object。
Function.prototype__proto__ === Object.prototype