该笔记参考自《你不知道的JavaScript上卷》
一.(原型)继承
1.检查”类”关系
- 假设现在有个对象
a
,如果寻找对象a
委托的对象呢?(假设存在)
①方法一:instanceof
function Foo(){}
var a = new Foo();
//在a的整条[[Prototype]]链中是否存在Foo.prototype的对象?
a instanceof Foo;
>>>true
- 该方法有个局限性:
只能处理对象(
a
)和函数(带prototype
引用的Foo
)之间的关系。
②方法二:isPrototypeOf()
方法
function Foo(){}
var a = new Foo();
//Foo.prototype是否在a的[[Prototype]]链中
Foo.prototype.isPrototypeOf(a);
>>>true
只需要两个对象就可判断它们之间的联系:
//b是否出现在c的[[Prototype]]链中?
b.isPrototypeOf(c);
③方法三:__proto__
([bunder]笨蛋proto
),在ES6
之前并不是标准。
function Foo(){}
var a = new Foo();
a.__proto__ === Foo.prototype;
>>>true
-
__proto__
并不存在于你正在使用的对象中(a
),实际上,它和其他的常用函数(toSring()
、isPrototypeOf()
等)一样,存在于内置的Object.prototype
中。(它们都是不可枚举的)
④如何直接获取一个对象的[[Prototype]]
链,ES5
中的方法:
function Foo(){}
var a = new Foo();
Object.getPrototypeOf(a) === Foo.prototype;
>>>true
二.对象关联
1.[[Prototype]]
机制就是存在于对象中的一个内部链接。
2.那这个内部链有什么用?
- 如果在对象上没有找到需要的属性或者方法引用,引擎就会继续在
[[Prototype]]
关联的对象上继续查找。
3.[[Prototype]]
机制的意义到底是什么?
var foo = {
fun: function(){
console.log('Tell me something interesting.');
}
};
var bar = Object.create(foo);
bar.fun();
>>>Tell me something interesting.
Object.create()
方法会创建一个新对象(bar
)并把它关联到我们指定的对象(foo
),这样以来,我们既可以充分发挥[[Prototype]]
的威力(委托),又避免了不必要的麻烦(如:使用new
的构造函数调用回生成prototype
和constructor
引用)。
4.Object.create(null);
是什么情况?
Object.create(null)
会创建一个拥有空[[Prototype]]
链接的对象,这个对象无法委托。由于这个对象没有原型链,所有instanceof
操作符无法进行判断,总是返回false
。这些特殊的空[[Prototype]]
对象通常被称作”字典”,它们完全不会受到原型链的干扰,因此非常适合用来储存数据。
5.Object.create()
是在ES5
中新增的函数,那么怎么兼容ES5
之前的环境?
-
Object.create()
的polyfill
代码
var foo = {
fun: function(){
console.log('Tell me something interesting.');
}
};
Object.create2 = function(o){
function F(){}
F.prototype = o;
return new F();
};
var bar = Object.create2(foo);
bar.fun();
>>>Tell me something interesting.
6.直接委托和间接委托
①直接委托
var anotherObject = {
cool: function(){
console.log('cool!');
}
};
var myObject = Object.create(anotherObject);
myObject.cool();
>>>cool!
②间接委托
var anotherObject = {
cool: function(){
console.log('cool!');
}
};
var myObject = Object.create(anotherObject);
myObject.doCool = function(){
//内部委托
this.cool();
};
myObject.doCool();
>>>cool!
- 间接委托的优点:层次更加清晰,同时仍能发挥
[[Prototype]]
关联的威力。
三.小结
1.如果要访问对象中并不存在的一个属性,[[Get]]
操作就会查找对象内部[[Prototype]]
关联的对象。这个关联关系实际上定义了一条”原型链”,在查找属性时会对它进行遍历。
2.JavaScript机制中的一个核心:不会复制,对象之间是通过内部的[[Prototype]]
链关联的。
3.对象之间的关系不是复制而是委托。
4.委托行为意味着某些对象在找不到属性或方法引用时,会把这个请求委托给另一个对象。