一、原型式继承
2006年,Douglas Crockford在《JavaScript中的原型继承》中提到:
function object(o){
function F(){ }; //临时的构造函数,
F.prototype = o;
return new F();
}
我们来实践一下这个方案:
// 原型式继承:当传入的参数为构造函数实例
// 写一个工具函数 object
function object(o) {
function F() {};
F.prototype = o;
return new F();
}
//父构造函数
function Super() {
this.pbrand = 'super';
// 添加引用值
this.a = [1, 2, 3, 4, 5];
}
// 利用工具函数实现 :子 继承 父
let suber1 = object(new Super());
let suber2 = object(new Super());
// 测试实例对象之间的属性是否独立:原始值
suber1.pbrand = 'suber';
console.log(suber1);
console.log(suber2);
// 测试实例对象之间的属性是否独立:引用值
suber1.a.push(8);
console.log(suber1);
console.log(suber2);
分析结果:
-
实现了子对象实例之间的原型上的引用值 b 还是共享的!
-
ECMAScript5 增加了Object.create() 将原型式继承概念化,Object.create()与上面定义的object()效果相同
-
所以记住,原型上的属性在实例之间是共享的,改变引用值属性的话,会造成一变万变(也就是引用值共享)。
二、原型式继承 与 对象原型继承
- 从结果来看,这两种继承方式的效果都一样
- 如果,不需要创建构造函数,然后实现继承的话,原型式继承就非常合适,
三、寄生式继承
寄生式继承背后的思路类似于寄生够高函数和工厂模式:创建一个实现继承的函数(这里指create()),以某种方式增强对象,并返回这个对象
寄生式继承仍存在prototype对象上引用值共享问题!
基本的寄生式继承模式如下:
// 寄生式继承
function object(o) {
function F() {};
F.prototype = o;
return new F();
}
// 继承的工具函数:工厂模式
function create(obj) {
let o = object(obj);
return o;
}
let person = {
name: 'father',
friends: ['Jack', 'Rose']
}
let person1 = create(person);
let person2 = create(person);
person2.friends.push('Tom');
console.log(person1.friends);
console.log(person2.friends);