JS原型

在 JS 中,主要有两种创建对象的方法, 分别是对象字面量以及调用构造函数

1
2
3
4
5
6
7
//对象字面量
var obj1 = {};

//调用构造函数
var obj2 = new Object(); // typeof Object === 'function'

obj1.__proto__ === Object.prototype // true

prototype 、constructor

** 每个函数 **默认会有一个prototype属性指向它的原型对象,
该原型对象会有一个constructor的属性,该属性包含一个指针,指向prototype属性所在函数,即

1
Object.prototype.constructor === Object

__proto__

每一个对象都有一个隐式的__proto__属性,指向它们的构造函数的原型,即

1
obj1.__proto__ === Object.prototype // true
1
obj1.__proto__.constructor === Object // true

prototype 和 __proto__ 的区别

prototype函数才有的属性,__proto__对象和函数都有的属性(不是一个规范属性,只是部分浏览器实现了此属性,对应的标准属性是 [[Prototype]]

Object 和 Function 的关系

ObjectFunction的实例对象, Function.prototypeObject的实例对象。Object本质是函数,Function本质是对象

1
2
Object.__proto__ === Function.prototype;
Function.prototype.__proto__ === Object.prototype;

原型继承

利用 js 的原型,可以实现继承。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Box() {}
function Box2() {}
function Box3() {}

Box2.prototype = new Box();
Box3.prototype = new Box2();

var a = new Box2();
var b = new Box3();

a.__proto__ === Box2.prototype; // true
b.__proto__ === Box3.prototype; // true

// 原型链如下,到 null 终止
Box3.prototype.__proto__ === Box2.prototype; // true
Box2.prototype.__proto__ === Box.prototype; // true
Box.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true

除了Object的原型对象Object.prototype__proto__指向null,其他内置函数对象的原型对象(例如:Array.prototype)和自定义构造函数的__proto__都指向Object.prototype, 因为原型对象本身是普通对象。

ES5 有了 Object.create(),让我们更便捷地使用原型继承,Object.getPrototypeOfObject.setPrototypeOf 可以更自由地操控原型链。

1
2
3
4
5
6
7
8
9
function Box() {}
function Box2() {}
function Box3() {}

Box2.prototype = Object.create(Box.prototype)
Box3.prototype = Object.create(Box2.prototype)

console.log(Box3.prototype.__proto__ === Box2.prototype) // true
console.log(Box2.prototype.__proto__ === Box.prototype) // true