粗谈继承

注:在继承以前咱们须要了解一下构造函数和原型链的相关知识,下面我经过例子来讲明一下编程

/* * 所谓的构造函数,顾明思议就是函数,但其与普通函数也有不一样 * 1.构造函数是经过 new 关键字建立对象时调用的函数 * 2.一般构造函数咱们会将函数名字的首字母大写 */
  function Animal(name){
    this.name = name; // 实例上的属性
    this.ability = ['吃饭', '睡觉', '打豆豆']; // 实例上的属性
    this.eat = function(){ // 实例上的方法
        console.log('吃')
    }
  }
  Animal.prototype.address = {location: '大山'}; // 原型上的属性(公有属性)
  let animal1 = new Animal('老虎');
  console.log(animal1) // Animal { name: '老虎', ability: [ '吃饭', '睡觉', '打豆豆' ], eat: [Function] }
  let animal2 = new Animal('猫'); 
  console.log(animal2) // Animal { name: '猫', ability: [ '吃饭', '睡觉', '打豆豆' ], eat: [Function] }
  console.log(animal1.ability === animal2.ability); // false
  console.log(animal1.address === animal2.address); // true
  console.log(animal1.__proto__ === Animal.prototype); // true
  console.log(Animal.prototype.constructor === Animal); // true
  console.log(Animal.__proto__ === Function.prototype); // true
  console.log(Function.prototype.__proto__ === Object.prototype); // true
  console.log(Object.prototype.__proto__); // null
  /* * 一句话总结原型链:每个实例都有一个__proto__属性,指向该实例所属类的原型(prototype)【须要注意的是原型是Object的实例哦】;每个类的原型上都有一个constructor属性指向类的自己 */
复制代码

继承的定义

  • 【官方】继承是面向对象软件技术当中的一个概念。若是一个类别A“继承自”另外一个类别B,就把这个A称为“B的子类别”,而把B称为“A的父类别”也能够称“B是A的超类”。继承能够使得子类别具备父类别的各类属性和方法,而不须要再次编写相同的代码。在令子类别继承父类别的同时,能够从新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其得到与父类别不一样的功能。另外,为子类别追加新的属性和方法也是常见的作法。 通常静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,没法在执行期扩充。(注:文本内容来源某度)
  • 【我】我理解的继承无非就是两个互不相关的类经过一些特定的方法使其中一个类拥有另外一个类的属性或者方法,JS中我总结了为有三种继承场景
    • 一、子类继承父类实例上的属性/方法
    • 二、子类继承父类原型上的属性/方法
    • 三、子类继承父类实例和原型上的属性/方法

1、子类继承父类实例上的属性/方法(所谓的call继承)

function Animal(name){ // 父类
    this.name = name;
    this.eat = '吃肉'
}
Animal.prototype.address = {location: '大山'};

function Tiger(name){
    Animal.call(this);
    this.name = name;
    this.age = 5;
}
Tiger.prototype.say = function(){ // 子类
    console.log('说话')
}
let tiger = new Tiger('老虎')
console.log(tiger) // Tiger { name: '老虎', eat: '吃肉', age: 10 }
console.log(tiger.say) // [Function]
console.log(tiger.address) // undefined
复制代码

2、子类继承父类原型上的属性/方法

实现方式一(所谓的原型链继承)

function Animal(name){ // 父类
    this.name = name;
    this.eat = '吃肉';
}
Animal.prototype.address = {location: '大山'};

function Tiger(name){ // 子类
    this.name = name;
    this.age = 5;
}
Tiger.prototype.say = function(){
    console.log('说话');
}
Tiger.prototype.__proto__ = Animal.prototype;
let tiger = new Tiger('老虎');
console.log(tiger); // Tiger {name: '老虎', age: 10}
console.log(tiger.say); // [Function]
console.log(tiger.address) // {location: '大山'}
复制代码

实现方式二(经过Object.create/Object.setPrototypeOf)

function Animal(name){
    this.name = name;
    this.eat =  '吃肉';
}
Animal.prototype.address = {location: '大山'};

function Tiger(name){
    this.name = name;
    this.age = 5;
}
Tiger.prototype = Object.create(Animal.prototype);
// Tiger.prototype = Object.create(Animal.prototype,{constructor:{value:Tiger}});
// 上行代码等价于Object.setPrototypeOf(Tiger.prototype,Animal.prototype) ES6
Tiger.prototype.say = function(){
    console.log('说话')
}
let tiger = new Tiger('老虎')
console.log(tiger) // Animal { name: '老虎', age: 10 }
/* 这时候你会发现咱们明明建立的是Tiger的实例,可是咱们输出的缺是Animal的实例,这就关系到Object.create方法的实现了, * 下面代码咱们手写一版简单的Object.create方法(结合下文参考图) */
Object.create = function(parentPrototype,options={}){
    let Fn = function(){};
    Fn.prototype = parentPrototype;
    let fn = new Fn();
    if(options.constructor){
        fn.constructor = options.constructor.value
    }
    return fn;
}
/*不难看出咱们能够给Object.create传入options来改变constructor*/
复制代码

参考图

3、子类继承父类实例和原型上的属性/方法

实现方式一(所谓的寄生组合继承——上述的结合)

  • 这里我就不罗列代码了,相信文章前的你必定能经过上述来实现

实现方法二(ES6的class语法糖)

class Animal{
    static address(){ // 静态方法(只能原型调用) 在ES7中能够直接添加静态属性 static address = {location: '大山'}
        return {location: '大山'}
    }
    constructor(name){ // 实例属性
        this.name = name;
        this.eat = '吃肉'
    }
    say(){ // 原型上的方法
        return '说话'
    }
}

class Tiger extends Animal{
    constructor(name){
        super(name)
        this.name = name;
        this.age = 5;
    }
    sleep(){
        return '睡觉'
    }
}
let tiger = new Tiger('老虎');
console.log(tiger) // Tiger { name: '老虎', eat: '吃肉', age: 5 }
console.log(tiger.say()) // 说话
console.log(tiger.sleep()) // 睡觉
console.log(Animal.address()) // { location: '大山' }
console.log(Tiger.address()) // { location: '大山' }
复制代码
相关文章
相关标签/搜索