检查“类”关系
在Java这些面向类的语言中,检查一个实例的继承祖先叫做反射。在JavaScript里面,怎么检查对象的委托关联呢?
function Foo() {
//...
}
var a =new Foo();
如何通过反射找出a的祖先(委托关联)呢?
a instanceof Foo; //true
instanceof回答的问题是:在a的整条[[Prototype]]链中是否有指向Foo.prototype的对象。Foo.prototype.isPrototypeOf(a); //true
isPrototypeOf()回答的问题是:Foo.prototype是否出现在a的整条[[Prototype]]链中。
对象关联
[[Prototype]]机制就是存在于对象中的一个内部链接,它会引用其他对象。
该链接的作用:如果在对象上没有找到需要的属性或者方法引用,引擎就会继续在[[Prototype]]关联的对象上进行查找。同理,如果在后者中也没有找到需要的引用就会继续查找它的[[Prototype]],以此类推。这一系列对象的链接被称为“原型链”。
[[Prototype]]机制的意义
var foo = {
something: function() {
console.log("something");
}
};
var bar = Object.create(foo);
bar.something(); //something
我们不需要类来创建两个对象之间的关系,只需要通过委托来关联对象。Object.create()会创建一个新对象(bar)并把它关联到我们指定的对象(foo),这样既可以委托又避免了不惜要的麻烦(比如使用new的构造函数调用会生成.prototype和.constructor引用)。
注意:
思考下面代码:
var anotherObject = {
cool: function() {
console.log("cool!");
}
}
var myObject = Object.create(anotherObject);
myObject.cool(); //cool!
myObject没有cool()方法,但是关联到了anotherObject,所以可以输出。别人看你的代码的话就会很奇怪,在维护的时候就会变得头大了吧?
可以考虑下面这样的改进办法:
var anotherObject = {
cool: function() {
console.log("cool!");
}
}
var myObject = Object.create(anotherObject);
myObject.doCool = function() {
this.cool(); //内部委托!
}
myObject.doCool(); //cool!
我们调用的doCool()是存在于myObject中的,这样我们的API设计就清晰了。从内部来说,我们的实现遵循的是委托设计模式,通过[[Prototype]]委托到anotherObject.cool().
内部委托比起直接委托可以让API接口设计更加清晰!