javascript继承只有一种实现方式

只做总结,具体概念可以看我引用的博客文章。
引用:阮一峰博客

为什么我说只有一种继承,那就是原型链继承。实现方式虽然多,但本质只有这一种。
结论在第五条总结部分。

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的实现方式

实现:

扫描二维码关注公众号,回复: 13014441 查看本文章
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库的一些代码。

猜你喜欢

转载自blog.csdn.net/a519991963/article/details/95961435