只做总结,具体概念可以看我引用的博客文章。
引用:阮一峰博客
为什么我说只有一种继承,那就是原型链继承。实现方式虽然多,但本质只有这一种。
结论在第五条总结部分。
1. 空对象中介继承(函数类型+原型链方式)
优点:
- 空对象不占内存
- 修改子对象的constructor不会改变父对象的constructor
- 我认为是es6中extend的实现方式
实现:
function extend(child,parent){
// parent.apply(child); 不能在这里加,不然this.type就是child的静态方法了
var f = function(){}
f.prototype = parent.prototype;
child.prototype = new f();
child.prototype.constructor = child; // 注意:默认指向parent,这里改成自己
child.uber = parent.prototype; // 备用属性
}
小栗子一号:
var cat = function(name){
this.name = name;
this.type = 'dongwu'
}
cat.prototype.getName = function(){
console.log(`this name is: ${this.name}`)
}
cat.prototype.getType = function(){
console.log(`this type is: ${this.type}`)
}
var catFood = function(user, name){
cat.apply(this)
this.user = user;
this.name = name;
}
extend(catFood, cat);
catFood.prototype.getUser = function(){
console.log(`this user is: ${this.user}`)
}
console.log(catFood instanceof cat) //false
console.log(catFood.uber === cat.prototype) //uber属性的使用。
var foot = new catFood('maoliang', 'maomi')
foot.getName();
foot.getUser();
foot.getType();
console.log(foot instanceof catFood) //true
console.log(foot instanceof cat) //true
2.拷贝继承(函数类型+原型链拷贝方式)
优缺点:
我觉得还不如第一种空值继承法呢,破坏了原型链继承。
实现如下:
function extend(child,parent){
var c = child.prototype;
var p = parent.prototype;
for(var i in p){ // 使用for in来枚举所有属性(可枚举和不可枚举)
c[i] = p[i]
}
child.uber = parent.prototype;
}
3.非构造函数继承(对象类型+原型链方式)
优缺点:
主要是针对object类型, 且不支持复合类型,比如对象之类。
这也是Object.create()函数的伪代码
小栗子二号:
var extent = function(parent){
var f = function(){}
f.prototype = parent;
return new f();
}
var father = {
isfather: 'yes'
}
var son = extent(father);
console.log(son.__proto__ === father) // true
son.isSon = 'yes'
console.log(son.isfather) //yes
console.log(son.isSon) //yes
4. 不用prototype链的深拷贝继承(对象类型+拷贝方式)
优缺点:
jquery的实现方式
实现:
function extendCopy(p, c) {
var c = c || {};
for (var i in p) {
if (typeof p[i] === 'object') {
c[i] = Array.isArray(p[i]) ? [] : {};
extendCopy(p[i], c[i])
} else {
c[i] = p[i];
}
}
return c;
}
小栗子三号:
var Chinese = {
nation: '中国',
birthPlaces: ['北京', '上海', '香港']
};
var Doctor = extendCopy(Chinese);
Doctor.birthPlaces.push('厦门');
console.log(Doctor.nation); // 中国
console.log(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
console.log(Chinese.birthPlaces); //北京, 上海, 香港
5.总结(重点)
- 虽然上面有四种实现方式,但我认为,继承是针对函数的,毕竟根据instanceof的定义来说,对象是没有prototype的。
- 所以,继承只有一种就是函数的原型链继承(原型链拷贝方式破坏了继承,不能算数)。
- 而,对象可以有原型链和拷贝两种“继承”, 原型链的方式是Object.create的实现,拷贝是jquery的实现。
- 在jquery的实现中,并没有对函数做拷贝,具体源码详解可参考:文章
- 我认为YUI库的消失,可能和es5、es6有关,es5和es6可能借鉴了YUI库的一些代码。