JS的继承

94 阅读2分钟

一、继承相关概念

确认继承关系后:

  1. 子类的实例可以共享父类的方法
  2. 子类可以覆盖或扩展父类的方法
  3. 子类和父类都是子类实例的类型

二、继承的实现(常用几种)

  • 对象冒充(构造函数绑定) 原理:使用对象冒充(call或apply方法)继承基类,实质上是改变了this指针的指向
// 1.构造函数绑定方式
function Monkey(_type,_home) { 
    this.type = _type;
    this.home = _home;
    this.say = function(){
        alert("我是快乐的小猴子,家住"+this.home);
    }
}

function Hero(_HP) {
    this.HP = _HP;
}

//一个子类实现两个父类(属性、方法均可)
function Magic_monkey(_type,_home,arr,_HP){
    // Monkey.call(this,_type,_home)
    Monkey.apply(this,[_type,_home])  //注意apply与call不同处参数为数组
    Hero.call(this,_HP)
    this.skill = arr;
}

var wukong = new Magic_monkey('猴子','花果山',['七十二变','筋斗云'],1000)
alert(wukong.home)
alert(wukong.type)
alert(wukong.skill)
alert(wukong.HP)
wukong.say()
  • 原型链(使用prototype属性)
    • prototype 对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。

    • 原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的 prototype 属性。

    • 子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。

//2.原型链继承方式
// ~不支持多重继承。因为原型链会用另一类型的对象重写类的prototype属性
// ~子类的所有属性和方法都必须出现在prototype属性被赋值后。因为在它赋值前的所有方法都会被删除。
// 因为prototype属性被替换成了新对象,添加了新方法的原始对象将会被销毁
function Monkey2() { }
Monkey2.prototype.type = "猴子";
Monkey2.prototype.say = function(){
    alert("我是一只快乐的小猴子")
}

function Magic_monkey2(){}
// 将Magic_monkey2的prototype对象指向一个Monkey的实例。
// 相当于删除了prototype对象原先的值,然后赋予一个新值。
Magic_monkey2.prototype.skill = "法术";
Magic_monkey2.prototype = new Monkey2();

var suWukong = new Magic_monkey2();
// alert(suWukong.type)
// suWukong.say()

// alert(suWukong.skill)  //undefine , 属性必须在重写后定义
  • 混合模式 创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。
function Monkey3(_type,_home){
    this.type = _type;
    this.home = _home;
}
Monkey3.prototype.say = function(){
    alert("我是快乐的小猴子,家住"+this.home);
}

function Magic_mokey3(_type,_home){
    //用对象冒充继承父类Monkey3的属性
    Monkey3.call(this,_type,_home)
}
//用原型链继承父类Monkey3的方法
Magic_mokey3.prototype = new Monkey3()
var suXingzhe = new Magic_mokey3('猴子','水帘洞')

alert(suXingzhe.type)
alert(suXingzhe.home)
suXingzhe.say()

//总结:继承最好的方式就是,用对象冒充继承构造函数的属性,用原型链继承prototype对象的方法