型指向超类, 最后返回该临时对象的实例. 所以该实例的 [[ prototype ]] 便指向了超类, 即类似对超类进行了一次浅复制.
function object(o) {
function F(){};
F.prototype = o;
return new F();
}
const Person = {
name: 'lorry',
friends: ['A', 'B']
}
const anotherPerson = object(Person);
anotherPerson.name = 'Lourance'
anotherPerson.friends.push('C')
console.log(Person.name, Person.friends) // 'lorry', ['A', 'B', 'C']
上述的 object 函数就是 ES5 中的 Object.create()函数不传第二个参数的情况, 即Object.create(o)
等价于object(o)
寄生式继承
还记得寄生吗? 就是那只寄居蟹.
function createAnother(origin) {
const clone = object(origin)
clone.sayName = function() {
console.log(this.name)
}
return clone
}
const anotherPerson = createAnother(Person)
anotherPerson.sayName() // lorry
这种方式有两个弊端:
- 与构造函数类似, 这种方式无法复用函数.
- 寄生的通病不知道其继承的谁. instanceof 会失效.
寄生组合式继承
之前说过最常用的继承模式为组合式继承, 但是组合式继承有一个问题就是会重复调用超类两次, 为了解决这个问题就可以使用寄生组合式继承.
// 寄生模式
function inheritPrototype(child, parent) {
const prototype = Object(parent.prototype);
// 恢复 instanceof 原型链的追溯
prototype.constructor = child;
child.prototype = prototype;
}
function SuperType(name) {
this.name = name;
this.friends = ['A', 'B']
}
SuperType.prototype.sayName = function() {
console.log(this.name)
}
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
const subIns1 = new SubType('lorry', 26);
const subIns2 = new SubType('lorry', 26);
subIns1.sayName(); // lorry
subIns1.friends.push('C');
console.log(subIns1.friends); // ['A', 'B', 'C']
console.log(subIns2.friends); // ['A', 'B']
上述就是最合理的继承方式, 集寄生式继承和组合继承的优点于一身. YUI 这个库就采用了上述的继承方式.
由此, 整个关于对象的内容就说完了.总结一下 创建对象的方式:
- 工厂模式
- 构造函数模式
- 组合模式
继承的方式:
- 原型模式
- 寄生式模式
- 寄生组合式模式