知食记
搜索文档…
原型链
有用的参考:
JavaScript深入之从原型到原型链 · Issue #2 · mqyqingfeng/Blog
GitHub

上面参考中递进的图片实例

构造函数和实例原型
每一个JavaScript对象(除了 null )都具有的__proto__属性 | person.__proto__ === Person.prototype
每个原型都有一个 constructor 属性指向关联的构造函数 | Person === Person.prototype.constructor
一个构造函数可以生成多个实例, 因此没有原型指向实例的箭头
原型的原型 | Person.prototype.__proto__ === Object.prototype
蓝色线就是原型链 | Object的原型的原型为空 | Object.prototype.__proto__ === null

真的是继承吗?

继承意味着复制操作,然而 JavaScript 默认并不会复制对象的属性,相反,JavaScript 只是在两个对象之间创建一个关联,这样,一个对象就可以通过委托访问另一个对象的属性和函数,所以与其叫继承,委托的说法反而更准确些。

更全面的原型链图

要想理解这两张图,最好的做法是推演一下这几个表达式:
1
Function.prototype instanceof Object // true
2
Function.prototype.__proto__ === Object.prototype // true
3
4
Object instanceof Object;//true
5
Function instanceof Function; //true
6
7
Number instanceof Number;//false
8
9
Function instanceof Object;//true
10
11
Foo instanceof Object; //true
12
Foo instanceof Function;//true
13
Foo instanceof Foo;//false
Copied!
自己总结
1
function A(){}
2
const a = new A()
3
4
a.__proto__ === A.prototype
5
A.__proto__ === Function.prototype
6
Function.__proto__ === Function.prototype
7
Object.__proto__ === Function.prototype
8
9
Function.prototype.__proto__ === Object.prototype
10
Object.prototype.__proto__ === null
Copied!

instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
1
// 模拟实现 右边变量的原型存在于左边变量的原型链上
2
function instanceOf(left, right) {
3
let leftValue = left.__proto__
4
let rightValue = right.prototype
5
while (true) {
6
if (leftValue === null) {
7
returnfalse
8
}
9
if (leftValue === right) {
10
returntrue
11
}
12
leftValue = leftValue.__proto__
13
}
14
}
Copied!

只有函数有原型链

1
let a = {}
2
let b = function () { }
3
console.log(a.prototype) // undefined
4
console.log(b.prototype) // { constructor: function(){...} }
Copied!

不要再使用 __proto__

__proto__属性没有写入 ES6 的正文,而是写入了附录。
原因是它本质上是一个内部属性,而不是一个正式的对外的 API,只是由于浏览器广泛支持,才被加入了 ES6
标准明确规定,只有浏览器必须部署这个属性,其他运行环境不一定需要部署,而且新的代码最好认为这个属性是不存在的

推荐使用 Object.getPrototypeOf Object.setPrototypeOf Object.create

所以无论从语义的角度,还是从兼容性的角度,都不要使用这个属性,应该使用:Object.getPrototypeOf(target)(读操作)、Object.setPrototypeOf(target)(写操作)、Object.create(target)(生成操作)代替
最近更新 2yr ago