好,那就让我们一步步打造,首先让我们来看下继承原本的写法:
<script> <BR>var Person = function(name, age) { <BR>this.name = name; <BR>this.age = age; <BR>} <BR>Person.prototype.SayHello = function () { <BR>alert(this.name + "," + this.age); <BR>}; <BR>var Programmer = function (name, age, salary) { <BR>Person.call(this, name, age); <BR>this.salary = salary; <BR>}; <BR>Programmer.prototype = new Person(); <BR>var pro = new Programmer("kym", 21, 500); <BR>pro.SayHello(); <BR></script>
我们看到,在实际上,继承的根本就在于这一步Programmer.prototype=new Person()。也就是说把Person加到原型链上。这一点在Javascript学习笔记7——原型链的原理 已经有过比较详尽的解释。
那也就是说,我们实现的关键就在于原型链的打造。
在上文中,我们用JSON来打造了一个原型,其原型链是p.__proto__=Person。那么我们希望在这个上封装继承,那么原型链应该是p.__proto__.__proto__=SuperClass,也就是说Person.__proto__=SuperClass。但是按照我们上面代码的继承方法,原型链关系是Person.__proto__=SuperClass.prototype。
这个和我们在上文中一样,我们的办法就是借助一个辅助函数,将原来的函数内的属性赋给X,然后令X.prototype=SuperClass即可,也就是说我们将子原型进行一个封装。
好,就按照这个思路,我们来实现利用原型链的继承关系的封装。
<script> <BR>var Factory = { <BR>Create: function (className, params) { <BR>var temp = function () { <BR>className.Create.apply(this, params); <BR>}; <BR>temp.prototype = className; <BR>var result = new temp(); <BR>return result; <BR>}, <BR>CreateBaseClass: function (baseClass, subClass) { <BR>var temp = function () { <BR>for (var member in subClass) { <BR>this[member] = subClass[member]; <BR>} <BR>}; <BR>temp.prototype = baseClass; <BR>return new temp(); <BR>} <BR>}; <BR>var People = { <BR>Create: function (name, age) { <BR>this.name = name; <BR>this.age = age; <BR>}, <BR>SayHello: function () { <BR>alert("Hello,My name is " + this.name + ".I am " + this.age); <BR>} <BR>}; <BR>var Temp = { <BR>Create: function (name, age, salary) { <BR>People.Create.call(this, name, age); <BR>this.salary = salary; <BR>}, <BR>Introduce: function () { <BR>alert(this.name + "$" + this.age + "$" + this.salary); <BR>} <BR>}; <BR>var Programmer = Factory.CreateBaseClass(People, Temp); <BR>var pro = Factory.Create(Programmer, ["kym", 21, 500]); <BR>pro.SayHello(); <BR></script>
这样就完成了我们对继承关系的封装。当然,我们也可以不单独写一个变量:
var Programmer = Factory.CreateBaseClass(People,
{
Create: function (name, age, salary) {
People.Create.call(this, name, age);
this.salary = salary;
},
Introduce: function () {
alert(this.name + "$" + this.age + "$" + this.salary);
}
});
当然,这全凭个人爱好了,个人认为第一种办法相对更清晰一些,但是第二种办法则更优雅。