您好,欢迎访问一九零五行业门户网

javascript 原型模式实现OOP的再研究_javascript技巧

复制代码 代码如下:
复制代码 代码如下:
function a()
{
this.v1 = 10;
}
a.prototype.print = function()
{
alert(this.v1);
}
function b()
{
}
b.prototype = new a();
new b().print();
运行这段代码输出是10,看起来好像是类b继承了类a的方法print,并产生了正确的输出,实际上的执行流程是在类b生成的对象中,不能直接得到方法print,于是在它的prototype属性中查找对应的方法,这个方案的出发点很好,类b中存在就调用类b的,否则调用它的prototype属性(类a)中的同名方法。然而有时候我们需要子类的方法调用父类同名的方法,比如类b改为
复制代码 代码如下:
function b()
{
this.v2 = 15;
}
b.prototype = new a();
b.prototype.print = function()
{
this.prototype.print.call(this);
alert(this.v2);
}
new b().print();
其中,this.prototype.print就是类a对应的print方法,输出是10和15,好像解决了问题,实际上不然,我们再继承一层
复制代码 代码如下:
function c()
{
this.v3 = 20;
}
c.prototype = new b();
c.prototype.print = function()
{
this.prototype.print.call(this);
alert(this.v3);
}
new c().print();
我们期待的输出依次是10, 15, 20, 但是很不幸,这样写的结果是系统会陷入死循环
因为在执行这个方法时,
复制代码 代码如下:
c.prototype.print = function()
{
this.prototype.print.call(this);
alert(this.v3);
}
将会循环的调用以下方法,直到堆栈溢出
复制代码 代码如下:
b.prototype.print = function()
{
this.prototype.print.call(this);
alert(this.v2);
}
正确的写法此时应该变为
复制代码 代码如下:
b.prototype.print = function()
{
a.prototype.print.call(this);
alert(this.v3);
}
c.prototype.print = function()
{
b.prototype.print.call(this);
alert(this.v3);
}
但是在继承关系发生了改变的情况下,需要改动相当多的对父类的引用,这也不是最佳的办法,在实际应用中,可以考虑使用_super来代替父类的名称,_this来代替自身的名称,然后用一个标准的方法将他们替换成[super].prototype或者[this].prototype,从而没有歧义的调用指定的方法,这才是javascript的oop的真正解决方案,相关的代码如下:
复制代码 代码如下:
/*
在使用oop继承体系时, 首先要定义类, 最后执行extendsof初始化类, 使用_super引用父类, 如, 使用_this引用本身的方法,
例如:
function extend2()
{
_super();
}
extend2.prototype.setvalue = function(value)
{
_super.setvalue(value);
alert(extend2: + value);
}
extend2.extendsof(extend1);
类继承树的根为object. 注意: 所有使用了转义的成员函数都必须定义在extendsof方法调用之前.
对象可以设定一个自动运行的初始化代码, 以下划线开头, 名称与对象名称相同, 如
object._object = function() {...}
如果对象的初始化代码不存在, 将自动寻找父对象的初始化代码, 直到全部查找完毕
复制代码 代码如下:
function.frblock = / *(([^^\\]|\\)*|'([^'^\\]|\\')*'|\/([^\/^\\]|\\.)*\/) */;
function.frspace = /\s+/g;
function.frsign = / ?(^|;|:||\?|,|\.|\/|\{|\}|\[|\]|\-|\+|\=|\(|\)|\*|\^|\%|\|) ?/g;
function.frrefer = /_(super|this)(\.[^(]+)?\(([^\)]*)\)/;
function.prototype.fcompile = function(name)
{
//检查是类的构造函数还是类的属性, name参数为空表示是构造函数
if (name)
{
//类的属性不是函数实现, 直接赋值到子类后退出
if (typeof this.prototype[name] != function)
{
window[this.fclassname].prototype[name] = this.prototype[name];
return;
}
var s = this.prototype[name].tostring();
}
else
{
var s = this.tostring();
}
var b = ;
var r;
//过滤空白字符
while (r = function.frblock.exec(s))
{
s = regexp.rightcontext;
b += regexp.leftcontext.replace(function.frspace, ).replace(function.frsign, $1) + r[1];
}
b += s.replace(function.frspace, ).replace(function.frsign, $1);
var i = b.indexof(();
var j = b.indexof(), i);
if (!name)
{
this.fclassname = b.substring(9, i);
}
var cn = this.fclassname;
var arg = b.substring(i + 1, j);
s = b.substring(j + 2, b.length - 1);
b = ;
//进行调用转义, 将_super,_this替换为指定的方法
for (var n = 0; r = function.frrefer.exec(s); n++)
{
if (r[2])
{
if (!name && !n)
{
b = this.fsuperclass.fclassname + .apply(this,arguments);;
}
r[2] = .prototype + r[2];
}
else if (r[1] == this)
{
//js函数不区分参数的差异, 构造函数不允许递归调用自身
throw constructor call mustn't be \_this();\ in a constructor;
}
else if (name || regexp.leftcontext)
{
throw constructor call must be the first statement in a constructor;
}
else
{
r[2] = ;
}
s = regexp.rightcontext;
b += regexp.leftcontext + (r[1] == this ? cn : this.fsuperclass.fclassname) + r[2] + (r[3] ? .call(this, + r[3] + ) : .apply(this,arguments));
}
if (n)
{
b += s;
}
else if (name)
{
//没有针对_this,_super的调用, 不用编译
window[cn].prototype[name] = this.prototype[name];
return;
}
else
{
//没有对父类构造函数的调用时, 自动添加
b = this.fsuperclass.fclassname + .apply(this,arguments); + s;
}
//编译结果赋值
if (name)
{
eval(cn + .prototype. + name + =function( + arg + ){ + b + });
}
else
{
eval(cn + =function( + arg + ){ + b + ;if(this.constructor== + cn + ) + cn + ._ + cn + .apply(this,arguments);});
window[cn].fclassname = cn;
}
}
function.prototype.extendsof = function(superclass)
{
this.fsuperclass = superclass;
//编译类的全部函数
this.fcompile();
for (var name in this.prototype)
{
this.fcompile(name);
}
var clazz = window[this.fclassname];
clazz.fsuperclass = superclass;
//复制父类中子类没有实现的函数和属性
var prototype = clazz.prototype;
for (var name in superclass.prototype)
{
if (!prototype[name])
{
prototype[name] = superclass.prototype[name];
}
}
//复制初始化方法, 形式如object._object
for (var c = this; ; c = c.fsuperclass)
{
if (c[_ + c.fclassname])
{
clazz[_ + clazz.fclassname] = c[_ + c.fclassname];
return;
}
}
}
/*
内置object类为oop提供的支持
*/
object.fclassname = object;
object._object = function.instance;
object.prototype.instanceof = function(clazz)
{
for (var c = this.constructor; c; c = c.fsuperclass)
{
if (c === clazz)
{
return true;
}
}
return false;
}
其它类似信息

推荐信息