javascript 中种种继续体式格局的优缺点

javascript中完成继续的体式格局有很多种,平常都是经由过程原型链和组织函数来完成。下面临种种完成体式格局举行剖析,总结各自的优瑕玷。

一 原型继续

let Super = functioin(name = 'eric') {
    this.name = name;
    this.getName = function() {
        return this.name;
    }
}

let Sub = function(sex = 'male') {
    this.sex = sex;
}
Sub.prototype = new Super('eric');  //经由过程转变原型对象完成继续
Sub.prototype.constructor = Sub // 坚持组织函数和原型对象的完整性
let sub1 = new Sub('male')
     sub2 = new Sub('female');

console.log(sub1.getName()); // eric
console.log(sub1.hasOwnProperty('name')) // false 申明是继续而来的属性
console.log(sub1.getName === sub2.getName) // true,复用了要领
     

长处:父类的要领(getName)获得了复用。

瑕玷:同理父类的属性(name)也是复用,即子类实例没有本身的属性。

二 组织函数完成继续

let Super = function(name = 'eric') {
    this.name = name;
    this.getName = function() {
      return this.name;
    }
  }
  let Sub = function(name, sex) {
    Super.call(this, name);
    this.sex = sex;
  }
  let sub1 = new Sub('eric', 'male');
  let sub2 = new Sub('ada', 'female');
  console.log(sub1.name) // 'eric'
  console.log(sub1.hasOwnProperty('name')) // true 申明不是继续而来,是本身的属性
  console.log(sub1.getName === sub2.getName) // false 要领没有获得复用

长处:子类的每一个实例都有本身的属性(name),不会相互影响。

瑕玷:然则继续父类要领的时刻就不须要这类特征,没有完成父类要领的复用。

三 组合式继续

let Super = function(name = 'eric') {
    this.name = name;
}
Super.prototype = {
    constructor: Super,
    getName() {
        return this.name;
    }
}
let Sub = function(sex) {
    Super.call(this, 'eric'); //继续父类属性
    this.sex = sex;
}
Sub.prototype = new Super('eric'); //继续父类要领
Sub.prototype.constructor = Sub;
let sub1 = new Sub('male'),
    sub2 = new Sub('female');
console.log(sub1.name); // 'eric'
console.log(sub1.hasOwnProperty('name')); // true 本身的属性
console.log(sub1.getName === sub2.getName); // true 复用了要领
console.log(Sub.prototype) // { name: "eric" }
console.log(sub1) // { name: "eric", sex: "male" }

长处:继续了上述两种体式格局的长处,摒弃了瑕玷,复用了要领,子类又有各自的属性。

瑕玷:由于父类组织函数被执行了两次,子类的原型对象(Sub.prototype)中也有一份父类的实例属性(name),而且这些属性会被子类实例(sub1,sub2)的属性覆蓋掉(即经由过程sub1.name接见不到Sub.prototype上的name属性),也存在内存糟蹋。

四 寄生组合式继续

let Super = function(name = 'eric') {
    this.name = name;
}
Super.prototype = {
    constructor: Super,
    getName() {
        return this.name;
    }
}
let Sub = function(sex, name) {
    Super.call(this, name);
    this.sex = sex;
}
// 组合继续的瑕玷就是在继续父类要领的时刻挪用了父类组织函数,从而形成内存糟蹋,
// 如今只需处理了这个题目就完美了。那在复用父类要领的时刻,
// 运用Object.create要领也能够到达目标,没有挪用父类组织函数,题目处理。
Sub.prototype = Object.create(Super.prototype);
// 固然这个处所也能够运用Object.setPrototypeOf(Sub.prototype, Super.prototype)
// 由于变动一个对象的山人原型(__proto__)对浏览器和js引擎都是很慢对操纵,所以发起运用Object.create()建立一个具有指定原型对象的新对象
Sub.prototype.constructor = Sub;

五 es6中的class

class Super() {
    constructor(props = { name: 'eric' }) {
        this.name = props.name;
    }
    setName(name) {
        this.name = name;
    }
    getName() {
        return this.name;
    }
}
class Sub extends Super {
    constructor(props) {
        super(props = { sex: 'male' }); // 建立实例,继续父类属性和要领
        this.sex = props.sex;
    }
}
let sub1 = new Sub({
    name: 'eric',
    sex: 'male'
})
let sub2 = new Sub({
    name: 'eric',
    sex: 'female'
})

sub1.setName('ada');
console.log(sub1.getName(),sub2.getName()) // ada,eric,属性没复用,各自实例都有本身的属性。
console.log(sub1.getName === sub2.getName) // true; 复用了父类的要领
console.log(Sub.prototype.sex) // undefined
// 子类原型对象上没有父类组织函数中赋值的属性,不是组合式继续

由以上效果能够看到es6中的class只不过是一种语法糖,经由过程上面的考证得知相符寄生组合继续的特性,但这只是猜想,class详细都做了哪些操纵还不是很清晰,背面有时间,对class做一下研讨。

    原文作者:夜未央
    原文地址: https://segmentfault.com/a/1190000009955064
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞