Object Prototype Extending
所有拓展原型链方法的总结
来源: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Summary_of_methods_for_extending_the_prototype_chain
New 构造函数法
function foo(){}
foo.prototype = {
foo_prop: "foo val"
};
function bar(){}
var proto = new foo;
proto.bar_prop = "bar val";
bar.prototype = proto;
var inst = new bar;
console.log(inst.foo_prop);
console.log(inst.bar_prop);
优点
- 兼容性优秀(IE5.5+)
- 速度非常快,基本是最快的实现。
- 可以被众多引擎无损优化。
缺点
- 要使用这种方法,这个函数必须被初始化。在初始化过程中(也就是上述代码中
proto
的建立过程中),构造函数应该在每次被使用时创造独立的值。然而,这种值只会被构造一次,很有可能引起不必要的麻烦。 - 在构造函数的初始化中,很多不需要的方法也可能被放到对象中。但是,只要足够小心去维护,这些都是JavaScript合理的行为,只要你充分理解原型链的概念和它们的原理,这些问题也可能变成特性从而可以加以利用。
Object.create
function foo(){}
foo.prototype = {
foo_prop: "foo val"
};
function bar(){}
var proto = Object.create(
foo.prototype
);
proto.bar_prop = "bar val";
bar.prototype = proto;
var inst = new bar;
console.log(inst.foo_prop);
console.log(inst.bar_prop);
优点
- 被所有的现代浏览器所支持(IE9+)
- 允许通过
Object.create
直接设定__proto__
的值,而且这种设定会被引擎充分优化,因为它只被设置了一次。 - 允许创建一个没有原型的对象,通过
Object.create(null)
。
缺点
- 不支持IE8-。
- 如果使用
Object.create
的第二个参数,这种构造有可能很慢,因为每个独立的对象(这里应该指的是字面量)都会创造对应的描述符对象(也就是哈希表)。如果被创造了过多的这种描述符,就会因为频繁GC而导致性能问题。
Object.setPrototypeOf
function foo(){}
foo.prototype = {
foo_prop: "foo val"
};
function bar(){}
var proto = {
bar_prop: "bar val"
};
Object.setPrototypeOf(
proto, foo.prototype
);
bar.prototype = proto;
var inst = new bar;
console.log(inst.foo_prop);
console.log(inst.bar_prop);
优点
- 兼容性良好(IE9+)
- 允许动态改变一个对象的原型链,甚至让一个被
Object.create(null)
创建的无原型对象拥有原型。
缺点
- 应该被弃用,而且性能很差。大多数的引擎都是通过推测对象的原型链从而进行针对性的优化。动态设置原型链会让这些优化完全失效,甚至使得引擎重新编译部分代码从而保证结果一致。
- 不被IE8-支持。
直接设置__proto__
function foo(){}
foo.prototype = {
foo_prop: "foo val"
};
function bar(){}
var proto = {
bar_prop: "bar val",
__proto__: foo.prototype
};
bar.prototype = proto;
var inst = new bar;
console.log(inst.foo_prop);
console.log(inst.bar_prop);
优点
- 被IE11+和现代浏览器所支持。
- 如果
__proto__
不是一个对象,这种方法不会引发异常。
缺点
- 跟
Object.setPrototypeOf
一样,性能比较糟糕而且应该弃用。动态改变原型链在什么时候都是开销较大的操作。 - 不支持IE10-。