JS如何实现继承(未完成 谨慎参考)

2019-11-14  本文已影响0人  moyahuang

《JS语言精粹》刷到继承部分,有点刷不动了。决定跟这一部分死磕到底。希望完成后也可以帮到其他初学的旁友们。

继承可以帮我们实现1. 代码重用 2. 以及进行规约

JS的对象采用原型继承(prototype-based inheritance)机制。当属性和方法添加到对象的原型上时,该对象及其后代便都会具备这些属性和方法。

在其他诸如C语言等程序语言中,通常都有一个函数叫做构造函数(constructor)。构造函数就是为对象实例赋初值的。JS中没有类(ES6以前),普通函数(function)即可以用作构造函数,不过为了跟普通函数进行区分,一般会把用作构造函数的普通函数名首字母大写。

当定义了这样一个函数(类)时

function Crane(a, b){}

JS会为Crane.prototype增加一个属性constructor,其值指向刚才定义的方法(对象)或构造函数(以下统称为构造函数)本身,并且该构造函数还包括下面几个属性

Crane.prototype={constructor: this}

用一张图可以表示为

constructor.png

同时,构造函数本身也有constructor属性,这个属性指向Function构造函数

function_constructor.png

注:ES6引入了关键词class,JS也可以像其他语言一样在class内部作用域定义构造函数。

构造函数模式如何继承

使用Parent.call

上面提到的构造函数使用关键词new即可创建对象,这种模式怎样实现继承呢?我们看到下面的例子

function Bird(type, color){
    this.type=type;
    this.color=color;
    this.fly=function(){
        console.log(this.color+' '+this.type+" is flying!");
    }
}
//Parrot也是鸟 它有所有Bird拥有的属性
function Parrot(type, color){
    Bird.call(this, type, color); //继承鸟的所有属性和方法
    this.talk=function(){
        console.log(this.color+' '+this.type+" is talking!")
    }
}

var prr=new Parrot("鹦鹉", "彩色de");
prr.talk();
prr.fly();

使用ES6的类关键词

ES6引入了类机制,使用关键词extends即可实现继承。上面的代码可以改成这样

class Bird{
    constructor(type, color){
        this.type=type;
        this.color=color;
    }
    fly(){
        console.log(this.color+' '+this.type+" is flying!");
    }
}

class Parrot extends Bird{
    constructor(type, color){
        super(type, color);
    }
    talk(){ ... }
}

伪类模式(不推荐)

我认为伪类模式与上面的继承方法的不同点在于,子类的构造函数会包含所有的属性,而无法不会进行属性的传递。因其关键点在于将子类的原型设置为父类对象。下面看一个例子

var Mammal=function(name){
    this.name=name;
}
//注意这里要采用加强prototype的方式添加方法
Mammal.prototype.get_name=function(){
    return this.name;
}
Mammal.prototype.says=function(){
    return this.saying||'';
}
var Cat=function(name){
    this.name=name;
    this.saying='meow';
}
Cat.prototype=new Mammal();
Cat.prototype.get_name=function(){
    return this.says()+' '+this.name;//调用父类的方法
}
var myCat=new Cat("Katy");
console.log(myCat.get_name()); // "meow Katy"

当然,《JS语法精粹》里对上述的一些步骤进行了方法的封装,使程序表达性更高,隐藏了重复写prototype的一些"ugliness"。

var Cat=function(name){
    this.name=name;
    this.saying="meow";
}.inherits(Mammal)
.method("get_name",function(){...});

其中inherits是这么定义的

Function.method("inherits",function(Parent){
    this.prototype=new Parent();
    return this;
})

Function.method也是《JS语法精粹》定义的一个方法,常常用到,这里我写一遍算是复习了

Function.prototype.method=function(name, func){
    if(this.prototype[name]!=="function"){
        this.prototype[name]=func;
        return this;
    }
}

参考资料

  1. https://www.freecodecamp.org/news/a-guide-to-prototype-based-class-inheritance-in-javascript-84953db26df0/

  2. 《JS语法精粹》

上一篇下一篇

猜你喜欢

热点阅读