继承(Inheritance)
(三) 原型式继承
原型式继承与类式继承截然不同, 个人感觉比类型继承简单得多, 类式继承 每个实例中都有类的实例属性的一份副本, 实例方法只存在一份
原型式继承不用定义类, 只需定义一个对象就行, 这个对象可以被其它的对象重用, 定义的这个对象叫原型对象 - prototype object
书的作者提醒我们学习原型式继承的时候一定要忘记上一篇关于类和实例的一切知识 - -
/* Person Prototype Object. */
var Person = {
name; 'default name',
getName: function() {
return this.name;
}
}
var reader = clone(Person);
console.log(reader.getName()); // 'default name'
用到了 clone() 函数, 下面给出 clone() 内部怎么工作的:
/* Clone function. */
function clone(object) {
function F() {};
F.prototype = object;
return new F; // == return new F();
}
clone() 仅仅是创建了空对象, prototype 指向参数 object 而已.
clone() 的对象不像类继承那样有类实例属性的副本. Sorry.. 应该忘记类继承!
clone 而来的 reader 本身没有父类的属性副本, 也就表现出了一个问题:
(1) 对继承而来的成员的读和写的不对等性
读 reader.name 的时候, reader 本身没有这个属性, 在 reader.prototype 里找到了.
写 reader.name 的时候, 直接在 reader 里写, 不会写到 reader.prototype 里, 这很好理解.
Javascript's hasOwnProperty() 方法可以用来区分是实例对象的成员, 还是继承来的成员.
(四) 类式继承和原型式继承的对比
类式继承和Java C++等比较像, 大家熟悉.
原型式继承没有类那样熟, 但是这种方法简洁 且 省内存.
两种方式可互换.
(五) 继承与封装
只有公用成员和特权成员能够被继承下来.
第一篇中的门户大开型是最合适继承的, 因为其中成员全是公用的.
(六) 掺元类
创建一个具有很多方法的掺元类, 然后用这个类去扩充其它其它类.
/* Mixin class. */
var Mixin = function() {};
Mixin.prototype = {
foo1: function() {},
foo2: function() {}
};
augment(Author, Mixin);
var author = new Author();
author.foo1();
author.foo2();
augment(A, B) 作用是将 B.prototype 中每一个成员添加到 A.prototype 中.