我只能简化到如此地步了 感觉还差一点没想到 大家都看看 帮小弟指点迷津
Class.wrap=function(self, key, method){
return function(){//
var caller = this.caller, current = this._current;
this.caller = current; this._current = arguments.callee;
var result = method.apply(this, arguments);
this._current = current; this.caller = caller;
return result;
}
}
var a=function(){}
var b=function(){}
b.prototype.b=Class.wrap(this,'b',function(){this.p()})
b.prototype.p=Class.wrap(this,'p',function(){alert(this.caller)})
var bb=new b
bb.b()
Class.wrap=function(self, key, method){
return function(){//
var caller = this.caller, current = this._current;
this.caller = current; this._current = arguments.callee;
var result = method.apply(this, arguments);
this._current = current; this.caller = caller;
return result;
}
}
var a=function(){}
var b=function(){}
b.prototype.b=Class.wrap(this,'b',function(){this.p()})
b.prototype.p=Class.wrap(this,'p',function(){alert(this.caller)})
var bb=new b
bb.b()
解决方案 »
- 罕见的js错误: typeerror:object #<a document> has no method load
- 请教一下多个frame之间取值的问题
- 急~~~~在线等待·~~ 表单传值和弹窗求助
- 深经半夜发帖求助,如何禁止子窗口刷新父窗口?详情请进>>
- 随机数组 方法的疑惑
- 下拉列表如何互相控制?
- 怎样识别用户用的输入法
- 请问怎样清除<input type="file" name="file">里面的值?
- 浏览器参数控制问题?
- javascript和vbscript的冲突问题,急急急!!!
- IE8.0执行JavaScript的速度为什么那么慢?
- 再次发帖 http://topic.csdn.net/u/20090507/10/ae5e7cb5-8691-432d-ae8a-d99084079f8f.html
再简化一下
var w=function( method){
return function(){//
var caller = this.caller, current = this._current;
this.caller = current; this._current = arguments.callee;
var result = method.apply(this, arguments);
this._current = current; this.caller = caller;
return result;
}
}
var a=function(){}
var b=function(){}
b.prototype.b=w(function(){this.p()})
b.prototype.p=w(function(){alert(this.caller)})
var bb=new b
bb.b()
这次可以正确弹出
有不对的地方 还请大家指点
Function.prototype.extend=function(x){
for(var i in x)this[i]=x[i]
return this
}var w=function(self, key, method){
return function(){//
var caller = this.caller, current = this._current;
this.caller = current; this._current = arguments.callee;
var result = method.apply(this, arguments);
this._current = current; this.caller = caller;
return result;
}.extend({_owner: self, _origin: method, _name: key});
}
var a=function(){}
a.prototype.b=w(this,'b',function(){alert('ssss')})//想调用a的这个同名函数
var b=function(){
var b=function(){}
b.parent =a;
b.prototype = new a;
b.prototype.parent=w(this,'parent',function(){
var name = this.caller._name, previous = this.caller._owner.parent.prototype[name];
if (!previous) throw new Error('The method "' + name + '" has no parent.');
return previous.apply(this, arguments);
})
return b
}
b.prototype.b=w(this,'b',function(){this.parent()})//这里调用a的同名函数 var bb=new b
var bbb=new bb
bbb.b()//弹出ssss
这个问题和昨天的问题有点不同吧.
关键是method传了进去.而且他是同一Function型的不同实体.
通过apply(this)把第一次的方法对象塞给了后续的方法对象.
而昨天的,你apply的是另一个方法.没把前面赋值的执行.等等我把运行顺序详细的说一下.
你在
var bb=new b
前加上
alert(b.prototype.b)
alert(b.prototype.p)
你会发现他们返回的方法描述是一样的.
但是内部是有差别的.
他们的method对象是不同的.
你可以在w的返回函数中alert一下就知道了.
在
var result = method.apply(this, arguments);
前后分别加上
alert(method)
你可以看到结果:
function(){this.p()}(原型属性b的方法)
function(){alert(this.caller)}(原型属性p的方法)
function(){alert(this.caller)}
function(){this.p()}所以在method.apply的同时.原型属性b的方法实际上是停止了的.
所以过程变量是依旧存在的.
var caller = this.caller, current = this._current;
alert("caller\n" + this.caller)
alert("_current\n" + this._current)
this.caller = current; this._current = arguments.callee;
alert("caller\n" + this.caller)
alert("_current\n" + this._current) 你会发现.第一步执行原型属性b的时候.
实际上能赋得值的是this._current
所以.在中断,并以b方法属性继续执行p的时候.
this._current实际上是拥有b方法的callee的
所以在做赋值的时候
this.caller得到的值得实际上就是current得到的this._current的值所以在执行p的参数方法时.就能打出this.caller的值了.
for(var i in x)this[i]=x[i]
return this
}var w=function(self, key, method){
return function(){//
var caller = this.caller, current = this._current;
this.caller = current; this._current = arguments.callee;
var result = method.apply(this, arguments);
this._current = current; this.caller = caller;
return result;
}.extend({_owner: self, _origin: method, _name: key});
}
var a=function(){}
a.prototype.b=w(this,'b',function(){alert('ssss')})
var b=function(){
var b=function(){}
//b.parent =a;
b.prototype = new a;
b.prototype.parent=w(this,'parent',function(){
var name = this.caller._name, previous = this.caller._owner.parent.prototype[name];
if (!previous) throw new Error('The method "' + name + '" has no parent.');
return previous.apply(this, arguments);
})
b.prototype.b=w(this,'b',function(){this.parent();alert("aa");})//<-----上面注释掉这句 也可以执行 其实上面就没调用这句 直接调用的a的方法
return b
}
b.prototype.parent =a;//加在这了 var bb=new b
var bbb=new bb
bbb.b()//先弹出ssss再弹出aa才是对的 这样保证肯定是调用的b的b(b里面调用的a)接下来 我会用更通俗的方法 替代这个方法
因为你调用实际是w(this,'b',function(){this.parent();alert("aa");})的返回值.继续关注.
var a=function(){
var b=function(){}
b.prototype.b=this.w//
return b//这里这个函数的this丢失了
}
a.prototype.w="wwww"
var aa=new a
var aaa=new aa
alert(aaa.b)//弹出wwww但是我上面的那些例子 却把this保存了下来 保存在了相应函数的_owner属性中这就能解释this.caller._owner.parent.prototype[name]; 这句话为什么能调用到a函数的方法的原因
var b=function(){}
alert(this.w)//this有w
return b//
}
a.prototype.w="wwww"
var aa=new a
alert(aa.w)//弹出undefined aa其实是b函数 而不是new a生成的this,所以this丢失了,a.prototype.w也丢失了,所以aa.w弹出undefined
b.prototype.b=this.w
我说怎么老调不对...a.prototype.w没有丢吧.付给了b了.没错aa是b函数.但不是实例.而且你赋值的值是给了b的.不是w...
在实例中才有原型属性的.你试下:function a(){}
a.prototype.a="www"
alert(a.a)
alert(new a().a)运行中的方法中.this也算是一个实例.
下面的代码其实和mootools的Class.js已经非常像了 使用这种方法 可以很简单的实现类继承function $type(x){
if(typeof x=='object'){
if(x instanceof Array){
return 'array'
}else if(x instanceof Function){
return 'function'
}else{
return 'object'
}
}else{
return typeof x
}
}Function.prototype.extend=function(x){
for(var i in x)this[i]=x[i]
return this
}var Class=function(params){
var newClass = function(){}.extend(this);//赋予Class.prototype上的方法 ,其实就是继承了Class的implement方法
newClass.implement(params);//
return newClass;}Class.wrap=function(self, key, method){
return function(){//
var caller = this.caller, current = this._current;
this.caller = current; this._current = arguments.callee;
var result = method.apply(this, arguments);
this._current = current; this.caller = caller;
return result;
}.extend({_owner: self, _origin: method, _name: key});
}Class.prototype.implement= function(key, value){//
if ($type(key) == 'object'){
for (var p in key) this.implement(p, key[p]);//p=options key[p]={}
return this;
}
var mutator = Class.Mutators[key];
if (mutator){
value = mutator.call(this, value);
if (value == null) return this;
}
var proto = this.prototype;//变更proto就变更了newClass.prototype switch ($type(value)){
case 'function':
if (value._hidden) return this;
proto[key] = Class.wrap(this, key, value);//return function(){}.extend()
break;
default: proto[key] = value;//newClass.prototype[key]=value }
return this; }
Class.Mutators = {
Extends: function(parent){ this.parent = parent;
this.prototype = new parent; this.implement('parent', function(){
var name = this.caller._name, previous = this.caller._owner.parent.prototype[name];
if (!previous) throw new Error('The method "' + name + '" has no parent.');
return previous.apply(this, arguments);
}); }
};//下面就可以这样调用了
var a=new Class({
a:function(){alert("aaaa")},
b:function(){alert(("bbbb"))},
c:function(x){alert(x)}
})
var b=new Class({
Extends:a,//Extends要写在第一个
b:function(){alert("b22222")},
c:function(){this.parent(33)}
})
var bb=new b
bb.a()//aaaa
bb.b()//b22222
bb.c()//33
下面这个更符合封装的特性 也更符合逻辑
Function.prototype.extend=function(x){
for(var i in x)this[i]=x[i]
return this
}var w=function(self, key, method){
return function(){//
var caller = this.caller, current = this._current;
this.caller = current; this._current = arguments.callee;
var result = method.apply(this, arguments);
this._current = current; this.caller = caller;
return result;
}.extend({_owner: self, _origin: method, _name: key});
}
var a=function(){}var b=function(){
var b=function(){}
a.prototype.b=w(b,'b',function(){alert('ssss')})//this-->改成了b
b.parent =a;
b.prototype = new a;
b.prototype.b=w(b,'b',function(){this.parent();alert("aa");})//this-->改成了b
b.prototype.parent=w(b, 'parent', function(){////this-->改成了b
var name = this.caller._name, previous = this.caller._owner.parent.prototype[name];
if (!previous)
throw new Error('The method "' + name + '" has no parent.');
return previous.apply(this, arguments);
})
return b
}var bb=new b
var bbb=new bb
bbb.b()//先弹出ssss再弹出aa
Function.prototype.extend=function(x){
for(var i in x)this[i]=x[i]
return this
}var w=function(self, key, method){
return function(){//
var caller = this.caller, current = this._current;
this.caller = current; this._current = arguments.callee;
var result = method.apply(this, arguments);
this._current = current; this.caller = caller;
return result;
}.extend({_owner: self, _origin: method, _name: key});
}var Class = function(params){
var b = function(){}
for (var p in params) {
if (p == 'Extends'){
var parent = params[p];
b.parent = parent;
b.prototype = new parent;
b.prototype.parent = w(b, 'parent', function(){//
var name = this.caller._name, previous = this.caller._owner.parent.prototype[name];
if (!previous)
throw new Error('The method "' + name + '" has no parent.');
return previous.apply(this, arguments);
})
continue
}
b.prototype[p] = w(b, p, params[p])
}
return b
}var a=new Class({
a:function(){alert("aaaa")},
b:function(){alert(("bbbb"))},
c:function(x){alert(x)}
})
var b=new Class({
Extends:a,//Extends要写在第一个
b:function(){alert("b22222")},
c:function(){this.parent(33)}
})
var bb=new b
bb.a()//aaaa
bb.b()//b22222
bb.c()//33
function $type(x){
if(typeof x=='object'){
if(x instanceof Array){
return 'array'
}else if(x instanceof Function){
return 'function'
}else{
return 'object'
}
}else{
return typeof x
}
}function $unlink(object){
var unlinked;
switch ($type(object)){
case 'object':
unlinked = {};
for (var p in object) unlinked[p] = $unlink(object[p]);
break;
case 'array':
unlinked = [];
for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]);
break;
default: return object;
}
return unlinked;
};function $mixin(mix){//mix=混合
for (var i = 1, l = arguments.length; i < l; i++){
var object = arguments[i];
if ($type(object) != 'object') continue;
for (var key in object){
var op = object[key], mp = mix[key];
mix[key] = (mp && $type(op) == 'object' && $type(mp) == 'object') ? $mixin(mp, op) : $unlink(op);
}
}
return mix;
};
Function.prototype.extend=function(x){
for(var i in x)this[i]=x[i]
return this
}var wrap=function(self, key, method){//包裹起来
return function(){//
var caller = this.caller, current = this._current;
this.caller = current; this._current = arguments.callee;
var result = method.apply(this, arguments);
this._current = current; this.caller = caller;
return result;
}.extend({_owner: self, _origin: method, _name: key});
}var Class = function(params){
var b = function(){}
for (var p in params) {
value=params[p]
switch ($type(value)) {
case 'function':
if (p == 'Extends') {
b.parent = value;
b.prototype = new value;
b.prototype.parent = wrap(b, 'parent', function(){//
var name = this.caller._name, previous = this.caller._owner.parent.prototype[name];
if (!previous)
throw new Error('The method "' + name + '" has no parent.');
return previous.apply(this, arguments);
})
continue
}
b.prototype[p] = wrap(b, p, params[p])
break;
case 'object':
var previous = b.prototype[p];//
if ($type(previous) == 'object') $mixin(previous, value);
else b.prototype[p] = $unlink(value);
break;
case 'array':
b.prototype[p] = $unlink(value);
break;
default: b.prototype[p] = value;
}
}
return b
}var a=new Class({
a:function(){alert("aaaa")},
b:function(){alert(("bbbb"))},
c:function(x){alert(x)},
d:{a:"aaa"}
})
var b=new Class({
Extends:a,//Extends要写在第一个
b:function(){alert("b22222")},
c:function(x){this.parent(x)},
d:{b:"bbb"}
})
var c=new Class({
Extends:b,
c:function(){this.parent(33)},
d:{c:"ccc"}
})
var cc=new c
cc.a()//aaaa
cc.b()//b22222
cc.c()//33
alert(cc.d.a+' '+cc.d.b+' '+cc.d.c)//aaa,bbb,ccc