优先使用对象组合,而不是类继承;
类式继承:通过构造函数Child()来获取来自于另一个构造函数Parent()的属性;
- 默认模式:子类的原型指向父类的一个实例
function inherit(C, P) { C.prototype = new P(); } function Parent(name) { this.name = name || 'Adam'; } Parent.prototype.say = function () { return this.name; } function Child() {}; inherit(Child, Parent); var kid = new Child();
- 缺点:同时继承了两个对象的属性,效率低下;
- 借用构造函数:之继承在父构造函数中添加到this的属性;
function Parent(name) { this.name = name || 'Adam'; } Parent.prototype.say = function () { return this.name; } function Child(name) { Parent.apply(this, arguments); } var kid = new Child(); //并没有继承到say方法
- 多重继承:
function Cat() { this.legs = 4; this.say = function () { return 'meaoww'; } } function Bird() { this.wings = 2; this.fly = true; } function CatWings() { Cat.apply(this); Bird.apply(this); } var jane = new CatWings();
- 优点:可以获取扶对象自身成员的真实副本,且不会有子对象覆盖父对象的问题;
- 多重继承:
- 借用和设置原型:结合前两中模式,先借用构造函数,然后设置子构造函数的原型使其指向一个构造函数的实例;
function Child(a, b, c, d) { Parent.apply(this, arguments); } Child.prototype = new Parent();
缺点:父构造函数被调用两次;
-
共享原型:
function inherit(C, P) { C.prototype = P.prototype; }
即提供了简短迅速的原型链查询,也易导致影响其他对象;
-
临时构造函数:解决共享原型的问题
-
基本代码:
function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); }
-
存储超类:增加一个指向原始父对象的引用
function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; }
-
重置构造函数:考虑可能会用到constructor
function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; C.prototype.constructor = C; }
-
优化:避免每次需要继承时都创建
var inherit = (function () { var F = function () {}; return function (C, P) { F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; C.prototype.constructor = C; } })();
-
Klass: 模拟类的语法糖
var klass = function (Parent, props) { var Child, F, i; //新构造函数 Child = function () { if(Child.uber && Child.uber.hasOwnProperty('_construct')) { Child.uber._construct.apply(this, arguments); } if(Child.prototype.hasOwnProperty('_construct')) { Child.prototype._construct.apply(this, arguments); } } //继承 Parent = Parent || Object; F = function() {}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.uber = Parent.prototype; Child.prototype.constructor = Child; //添加实现方法 for(i in props) { if(props.hasOwnProperty(i)) { Child.prototype[i] = props[i]; } } //返回该Class return Child; } var Man = klass(null/*父类*/, { /*新类的实现*/ _construct: function (what) { console.log("Man's constructor"); this.name = what; }, getName: function () { return this.name; } }); var first = new Man('Adam'); first.getName(); var SuperMan = klass(Man, { _construct: function (what) { console.log("SuperMan's constructor"); }, getName: function() { var name = SuperMan.uber.getName.call(this); return "I am " + name; } }); var clark = new SuperMan('Clark kent'); clark.getName(); console.log(clark instanceof Man); console.log(clark instanceof SuperMan);
最好避免使用;适用于对类熟悉,对原型不熟的情况;
-