继承
1. 继承发展史
1.1 传统形式(原型链)
- 过多的继承了没用的属性
例子:
Grand.prototype.lastName = 'Ji'
function Grand() {
}
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = 'hehe';
}
var father = new Father();
Sun.prototype = father;
function Sun() {
}
var son = new Sun();
用这种原型链的方法,实例son为了继承grand的原型的lastName属性,不得不自下而上继承原型链上的所有属性。
不管是从用法上还是效率上都造成了浪费。
1.2 借用构造函数
-
不能继承借用构造函数的原型
-
每次构造函数都要多走一个函数
例子:
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, grade) {
Person.call(this, name, age, sex);
this.grade = grade;
}
var student = new Student();
利用call/apply借用构造函数。
这种方法便于开发,视觉上看起来更简洁,实际上并没有提升效率,反而还会多了一个调用环节。
1.3 共享原型
- 不能随便改动自己的原型
例子:
Father.prototype.lastName = 'Deng';
function Father() {
}
function Son() {
}
Son.prototype = Father.prototype;
共享原型可以封装成一个函数
Father.prototype.lastName = 'Deng';
function Father() {
}
function Son() {
}
function inherit(Target, Origin) {
Target.prototype = Origin.prototype;
}
inherit(Son, Father);
但是,Son和Father共用原型会导致,Son修改原型也会导致Father的原型发生改变,因为他们指向的是一个原型,这样的话,Son无法个性化的修改自己的原型。
1.4 圣杯模式
function inherit(Target, Origin) {
function F() {
}
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
Father.prototype.lastName = 'Deng';
function Father() {};
function Son() {};
inherit(Son, Father);
var son = new Son();
var father = new Father();
封装的继承函数还可以写成下面的形式。
var inherit (function () {
var F = function () {};
return function(Target, Origin) {
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
其中利用了闭包,实现了功能的封装和属性的私有化。
2. 小技巧(链式调用模式)
如何实现链式调用模式(模仿jquery)
var deng = {
smoke : function() {
console.log('Smoking');
return this;
},
drink : function() {
console.log('Drinking');
return this;
},
perm : function() {
console.log('perming');
return this;
}
}
deng.smoke().drink().perm().drink().smoke();
实现方法的连续调用。