【www.gdgbn.com--php基础】

继承机制不能采用动态化的原因是:prototype对象的唯一性。实例代码:
复制代码 代码如下:

function a (i) {
this.a = i;
if (typeof a._init == "undefined") {
a.prototype.func = function () {
return 0;
}
a._init = 1;
}
}
function suba (j) {
a.call(this, 1);
this.j = j;
if (typeof suba._init == "undefined") {
suba.prototype = new a();
suba.prototype.func_sub = function () {
return ++j;
}
suba._init = 1;
}
}
var sub_a = new suba(1);
alert(sub_a.func_sub()); //error: sub_a.func_sub is not a function

nicholas解释说在代码运行前,对象已被实例,并与prototype联系,在当前对prototype对象替换不会对它产生任何影响,即当前的替换是访问不到的,只有未来对象的实例才会反映出这种改变。于是第一个实例对象就会不正确。但第二个及以后的子类实例都没问题。 

  解决方法就是在构造函数外赋予新的prototype对象:
复制代码 代码如下:
function a (i) {
this.a = i;
if (typeof a._init == "undefined") {
a.prototype.func = function () {
return 0;
}
a._init = 1;
}
}
function suba (j) {
a.call(this, 1);
this.j = j;
if (typeof suba._init == "undefined") {
suba.prototype.func_sub = function () {
return ++j;
}
suba._init = 1;
}
}
suba.prototype = new a();
var sub_a = new suba(1);
alert(sub_a.func_sub()); //2 可惜这违反了我们为什么使用动态原型的初衷。
使用动态原型的初衷本来就是要让构造函数能“统一江山”,在视觉上让人觉得原型方法是类构造的一部分。
  以上是《网页特效高级程序设计》中对动态原型继承小节的大概内容。

  可是nicholas在先前的章节讲对象构造的【动态原型】方式中,似乎忘了提这个同样的问题。我们看看上文中最后一个例子:
复制代码 代码如下:

 

var obj = function (name) {
this.name = name;
this.flag = new array("a", "b");
if (typeof obj._init == "undefined") {
obj.prototype = {
showname : function () {
alert(this.name);
}
};
obj._init = true;
}
}
var obj1 = new obj("aa");
var obj2 = new obj("bb");
obj1.showname(); //error: is not a function
obj2.showname(); // bb;

 

  是的,这个问题其实和子类继承中出现的问题如出一辙,prototype在当前的替换是不会对该对象有任何影响的,只有在未来的实例中可见。如果按照nicholas处理动态原型继承的方式中说的一样,那就意味着只能在构造函数外边重新赋予prototype对象。那么这不就成了【构造函数/原型混合】方式了吗?所谓的【动态原型】方式也就不存在了...

 

  其实我们可以想想,为什么在【构造函数/原型混合】这种已经基本没有副作用的构建对象方式后面还要在写一节【动态原型】方式。作者的意图无非就是想让构造函数在视觉上更为统一么。其实仅仅要视觉上的统一可以不用动态原型的。
复制代码 代码如下:

var obj = function () {
function __initialize (name) {
this.name = name;
this.flag = new array("a", "b");
}
__initialize.prototype = {
showname : function () {
alert(this.name);
},
showflag : function () {
alert(this.flag);
}
}
return __initialize;
}();
var obj1 = new obj("aa");
var obj2 = new obj("bb");
obj1.showname(); // aa
obj2.showname(); // bb

其实上面的方式就可以算是视觉的统一了,obj的构造函数内通过__initialize来初始化属性,通过__initialize.prototype原型初始化方法。只不过稍微有点“小作弊”的感觉,__initialize代理了obj的初始化...
  下面是来自tangoboy的“构造类”的封装,其实思路和上面基本一致,唯一不同的是他把属性也用原型方式创建了,同时把初始化属性和方法都扔到了构造函数参数对象里。方便自定义:
复制代码 代码如下:

/* == form tangoboy == */
window["$class"] = {
//创建一个类 混合构造函数/原型方式
create: function(config) {
var obj = function(){},config = config||{};
//过滤构造方法和原型方法
obj = obj.prototype.constructor = config["__"]||obj;
delete config["__"];
obj.prototype = config;
return obj;
}
}
/* -- eg -- */
var man = $class.create({
__ : function (name) {
this.name = name;
},
sex : "male",
showname : function () {
alert(this.name);
}
});
var me = new man("ru");
me.showname(); //ru

其实如果硬要追求视觉的统一也可以不用动态原型的方式。说到底看看上面的思路,已经回溯到了我们最常用的“类构造”方式:
复制代码 代码如下:

var class = {
create : function () {
return function () {
this.initialize.apply(this, arguments);
}
}
}

相信上面这段代码大家或许都不会陌生

本文来源:http://www.gdgbn.com/jiaocheng/27871/