1. 原型式继承
注意:是原型式继承,不是原型链继承
该方法的原理是创建一个构造函数,构造函数的原型指向对象,然后调用 new 操作符创建实例,并返回这个实例,本质是一个浅拷贝。
伪代码如下:
function objcet (obj) {
function F () {};
F.prototype = obj;
return new F();
}
1.1 题目一
我们先看一个比较熟悉的东西
const cat = {
heart: '❤️',
colors: ['white', 'black']
}
const guaiguai = Object.create(cat)
const huaihuai = Object.create(cat)
guaiguai.colors.push('test')
console.log(guaiguai)
console.log(huaihuai)
console.log(guaiguai.colors)
console.log(huaihuai.colors)
答案:
{}
__proto__: colors: (2) ["white", "black","test"]heart: "❤️"
__proto__: Object
{}
__proto__: colors: (2) ["white", "black","test"]heart: "❤️"
__proto__: Object
❤️
["white", "black","test"]
["white", "black","test"]
这里用到了我们之前提到过的Object.create()
方法。
在这道题中,Object.create(cat)
会创建出一个__proto__
属性为cat的空对象。
注意:父类引入类型属性被共享了,记住!
1.2 题目二
在ES6之前没有Object.create()
方法,所以才会有开头的那段伪代码。
现在可以尝试自己实现一个Object.create()
想一下Object.create()
的作用
- 接受一个对象A
- 返回一个新对象B
- 并且
B.__proto__
-->A
所以就有了这么一个方法
function objcet (obj) {
function F () {};
F.prototype = obj;
return new F();
}
接下来看看效果是否和1.1一样
function object (obj) {
function F () {};
F.prototype = obj;
return new F();
}
const cat = {
heart: '❤️',
colors: ['white', 'black']
}
const guaiguai = object(cat)
const huaihuai = object(cat)
console.log(guaiguai)
console.log(huaihuai)
console.log(guaiguai.heart)
console.log(huaihuai.colors)
答案:
F {}
__proto__: colors: (2) ["white", "black","test"]heart: "❤️"
__proto__: Object
F {}
__proto__: colors: (2) ["white", "black","test"]heart: "❤️"
__proto__: Object
❤️
["white", "black","test"]
效果是和Object.create()
差不多(只不过我们自定义的object返回的对象是构造函数F创建的)。
注意:模拟后父类引入类型属性也被子例共享
现在我们尝试画张图
这就有小伙伴要问了,既然是需要满足
B.__proto__
-->A
这个条件的话,我这样写也可以实现啊
function object (obj) {
const newObj = {}
newObj.__proto__ = obj
return newObj;
}
可以用上面的例子试一试,确实可以实现
不过,我们是要模拟Object.create()方法,如果你都能使用__proto__,那为何不直接使用Object.create()呢?
1.3 题目三
无法向父类构造函数传参,并且父类构造函数中的属性无法继承,只能继承父类构造函数中的原型对象中的属性
要想继承父类构造函数中的属性,还得借用Parent.call
function Parent(){
this.name = 'a';
this.colors = ['red','yellow']
}
Parent.prototype.age = 21
function object (obj) {
function F () {
// Parent.call(this)
};
F.prototype = obj;
return new F();
}
const child1 = object(Parent.prototype)
const child2 = object(Parent.prototype)
console.log(child1);
console.log(child2);
答案:
2 总结
-
优点:
- 没有优点。⊙﹏⊙‖∣
-
缺点:
- 无法向父类构造函数传参
- 如果父类是构造函数,无法继承父类构造函数中的属性,只能继承父类构造函数的原型对象的属性(题1.3)
- 如果父类是普通对象,引入类型属性依然被子例共享(题1.2)
如果不当,还请老哥指出。