JS如何实现继承(未完成 谨慎参考)
《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构造函数
注: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;
}
}