传统的继承:
this.name = name || "default name";
if (typeof Person._initialized == "undefined") {
Person.prototype.getName = function () {
return this.name;
};
Person._initialized = true;
}
};
var Author = function (name, books) {
Person.call(this, name);
this.books = books || [];
/*
if (typeof Author._initialized == "undefined") {
Author.prototype = new Person();
Author.prototype.constructor = Author;
Author.prototype.getBooks = function () {
return this.books;
};
Author._initialized = true;
}
*/
};
Author.prototype = new Person();
Author.prototype.constructor = Author;
Author.prototype.getBooks = function () {
return this.books;
};
var p1 = new Person("zhangsan");
var p2 = new Person("lisi");
console.log(p1.getName());
console.log(p2.getName());
var a1 = new Author("Raymond", ["Pro Javascript Design Pattern", "Asp.net Framework"]);
var a2 = new Author("Rock", ["Oracle & PL SQL"]);
console.log(a1.getName());
console.log(a1.getBooks());
console.log(a2.getName());
console.log(a2.getBooks());
注意:注释的代码是我老喜欢用的动态原型。但是,很遗憾,它不能用在这里。因为,第一次调用Author构造函数执行到此处时,Author的实例对象已经被初始化了,改变Author的prototype已经不能对它形成影响(但是会对之后创建的Author对象实例起作用)。
为了更加OOP,我们自己模拟一下extend关键字。具体如下:
var F = function () { };
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
subClass.superClass = superClass.prototype;
if (superClass.prototype.constructor != superClass) {
superClass.prototype.constructor = superClass;
}
};
var Person = function (name) {
this.name = name || "default name";
if (typeof Person._initialized == "undefined") {
Person.prototype.getName = function () {
return this.name;
};
Person._initialized = true;
}
};
var Author = function (name, books) {
Author.superClass.constructor.call(this, name);
this.books = books || [];
};
extend(Author, Person);
Author.prototype.getBooks = function () {
return this.books;
};
还有一种被称为:prototypal的方式:
function F() { }
F.prototype = object;
return new F();
}
var Person = {
name: "default name",
configure: function (name) {
this.name = name;
},
getName: function () {
return this.name;
}
};
var Author = clone(Person);
Author.books = [];
Author.configure = function (name, books) {
// Person.configure(name);
this.name = name;
this.books = books;
};
Author.getBooks = function () {
return this.books;
};
这里对象类不再通过function实现,而是通过object literal。 因为没有构造器了,构造的实现迁移到configure方法中。遗憾的是,至今我仍没有找到合适的方法在Author类中override configure方法(被注释那一行),最后只能重复去赋值name。需要注意的是,这里author继承自Person的成员,在未被author重新创建(赋值)前,均通过prototype链指向的是对应于Person中的成员。虽然,书中提出用工厂方法来Person创建对象的成员,但我始终觉得它不是很合适,并且不能解决override的问题。
最后一个就是Mixin了。如下:
if (requestMemberArray) {
for (key in requestMemberArray) {
var memberKey = requestMemberArray[key];
if (givingClass.prototype[memberKey] && (isOverideExsitingMember || !receivingClass.prototype[memberKey])) {
receivingClass.prototype[memberKey] = givingClass.prototype[memberKey];
}
}
} else {
for (memberKey in givingClass.prototype) {
if (isOverideExsitingMember || !receivingClass.prototype[memberKey]) {
receivingClass.prototype[memberKey] = givingClass.prototype[memberKey];
}
}
}
}
var Person = function (name) {
this.name = name || "default name";
};
Person.prototype.getName = function () {
return this.name;
};
var Mixin = function () { };
Mixin.prototype = {
serialize: function () {
var output = [];
for (key in this) {
output.push(key + ':' + this[key]);
};
return output.join(',');
},
getName: function () {
return "This is test method from Mixin.";
}
};
augment(Person, Mixin, true);
var p1 = new Person("zhangsan");
var p2 = new Person("lisi");
alert(p1.getName());
console.log(p1.serialize());
其实,我觉得它更多的是一种组合的概念,而不是继承。
这里讲了继承的主干概念外,其实还涉及到了extend、clone、augment的模拟实现,可以将方法独立拿去使用。download