之前看了《JavaScript设计模式》中面向对象,对象继承的内容,书很经典,但实现方式我是不太理解。
今天看了《编写高质量代码-Web前端开发修炼之道》这本书中面向对象的相关内容,对js的继承,有点廓然开朗的感觉,循循善诱。这本书全篇都非常不错,值得一看。我想很大原因是国人原创,根据自身实践写出来的原因吧,跟外文翻译的还有有所不同的。
记录下js的继承方式,当然js的继承分类式继承和原型继承,我比较习惯类式继承。
Book基类:
var Book = function(name){ if(this.check(name)){ console.log("error"); throw new Error("name null"); } this.name = name; } Book.prototype = { check:function(name){ if(!name){ return true; } }, getName:function(){ return this.name; } }
继承方法:
function extend(subClz,superClz){ var F = function(){} F.prototype = superClz.prototype; subClz.prototype = new F(); subClz.prototype.constructor = subClz; subClz.superClass = superClz.prototype; if(superClz.prototype.constructor == Object.prototype.constructor){ superClz.prototype.constructor = superClz; } }
使用空函数F作为桥接,可以避免直接实例化父类时调用父类的构造函数带来额外开销,而且当父类的构造函数有参数时,想直接通过subClass.prototype = new superClass();实现父类构造函数的调用和原型链的继承是不行的。
subClz.superClass = superClz.prototype; if(superClz.prototype.constructor == Object.prototype.constructor){ superClz.prototype.constructor = superClz; }
添加这三句可以避免子类继承父类写Book.call(this,name);而是简单地写ArtBook.superClass.Constructor.call(this,name)便能实现。
并且在子类重写父类方法的时候,可以调用到父类的方法:
ArtBook.prototype.getName = functiion(){ return ArtBook.superClass.getName.call(this) + "!!!"; }
ArtBook子类:
var ArtBook = function(name,price){ ArtBook.superClass.Constructor.call(this,name); this.price = price; } extend(ArtBook,Book); ArtBook.prototype.getPrice = function(){ return this.price; } ArtBook.prototype.getName = function(){ return ArtBook.superClass.getName.call(this)+"!!!"; }
参考资料:
javascript设计模式:继承