js中的继承

ES5实现继承

声明一个Person对象,将该对象作为父级,而子级cPerson将要继承Person的所有属性与方法。

function Person(name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.getName = function() {
    return this.name;
}

构造函数继承

借助call方法,将父级的构造函数执行了一次,相当于将Person中的代码,在cPerson中复制了一份,其中的this指向为从Student中new出来的实例对象。call方法保证了this的指向正确,因此就相当于实现了继承。
缺点:即使实例对象拥有相同的方法,构造函数继承也会为每个实例对象创建单独的方法,浪费内存。

// 构造函数的继承
function cPerson(name, age, job) {
    Person.call(this, name, age);
    this.job = job;
}

原型继承

// 继承原型
cPerson.prototype = new Person(name, age)

// 添加更多方法
cPerson.prototype.getLive = function() {}

缺点:原型继承中的属性是共享的,如果一个实例对象对某属性进行了修改,那么另一个实例对象就会获取修改后的属性值。

组合继承

为了解决上面构造继承和原型继承中存在的缺点,出现了组合继承,一般不共享的属性通过构造继承,而需要共享的方法通过原型继承。
缺点:组合继承会调用两次父类构造函数的代码

function Person(name){
  this.name=name;
}
Person.prototype.sayName=function(){
  console.log(this.name+' '+this.gender+' '+this.age);
}
function Female(name,gender,age){
  Person.call(this,name);//第一次调用父类构造函数             
  this.age=age;
  this.gender=gender;
}
Female.prototype=new Person();//第二次调用父类构造函数
Female.prototype.constrcutor=Female;//因重写原型而失去constructor属性,所以要对constrcutor重新赋值

寄生组合继承

通过借用构造函数来继承属性,通过原型链来继承方法,不需要为子类指定原型而调用父类的构造函数,省去了上面第二次调用父类构造函数的步骤

通过创建父类原型的副本,并为其添加constructor,最后赋值给子类的原型。从而避免调用两次父类的构造函数,为其创建多余的属性

function inheritPrototype(Female,Person){ 
  var protoType=Object.create(Person.prototype);
  protoType.constructor=Female;
  Female.prototype=protoType;
}
inheritPrototype(Female,Person);
Female.prototype.sayAge=function(){
	console.log(this.name+' '+this.age);
}
//取代
//Female.prototype=new Person();
//Female.prototype.constrcutor=Female

//上面的代码相当于:
Female.prototype = Object.create(Person.prototype, {
    constructor: {     //重新指定构造函数
        value: Student
    }
    sayAge: {
        value: function() {
            return this.grade //添加新的方法
        }
    }
})

 var fm=new Female('skila','female',19);
 fm.sayName();//skila female 19
 fm.sayAge();skila  19
Object.create()

创建一个新对象,使用现有对象提供创建的新对象的__proto__

function create(proto, options) {
    // 创建一个空对象
    var tmp = {};

    // 让这个新的空对象成为父类对象的实例
    tmp.__proto__ = proto;

    // 传入的方法都挂载到新对象上,新的对象将作为子类对象的原型
    Object.defineProperties(tmp, options);
    return tmp;
}
Object.defineProperties()
var obj = {};
Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
  // etc. etc.
})

ES6实现继承

class Person{
  constructor(name,age){
    //这里的this指的是实例对象
    this.name = name
    this.age = age
  }
  //say绑定到Person.prototype
  say(){
    console.log('my name is ' + this.name + ", I am " + this.age)
  }
  //sayHobby绑定到Person.prototype
  sayHobby(){
    console.log('no hobby')
  }
  //sayName绑定到实例对象
  sayName = function(){
    console.log('my name is ' + this.name)
  }
  //sayAge绑定到实例对象
  sayAge = () => {
    console.log('I am ' + this.age + ' years old')
  }
}
//extends实现继承
class cPerson extends Person{
  constructor(name, age, hobby){
    super(name, age)
    this.hobby = hobby
  }
  sayHobby = function(){
    console.log('I like ' + this.hobby )
  }
}
const p = new cPerson('zs', 12, 'drawing')
console.log(p.name)  //zs
console.log(p.age)  //12
console.log(p.hobby)  //drawing
p.say() //my name is zs, I am 12
p.sayName() //my name is zs
p.sayHobby() //I like drawing
//实例对象上的属性可以被删除
delete p.sayHobby
p.sayHobby() //会通过原型链向上查找
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值