Javascript实现super()。

峭沙 2011-12-14 01:20:14
近日比较蛋疼,突然想起Java中的super很好用,心血来潮就用js模拟了下,欢迎拍砖。(注:由于super是js保留字,所有使用mysuper作为函数名。)
		Object.prototype.mysuper = function(){
var caller = arguments.callee.caller,
name;
for(var i in this){
if(this[i] === caller){
name = i;
break;
}
}
__proto = this.__proto__ || this.constructor.prototype;
return __proto[name]();
}
function Class(){
this.name = "class";
this.setName = function(name){
this.name = name;
}
this.getName = function(){
return this.name;
}
}
function Test(){
this.getName = function(){
return 'sub-' + this.mysuper();
}
}
Test.prototype = new Class();
Test.prototype.constructor = Test;

var a = new Test();
alert(a.getName());
...全文
876 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
darkhorse00000111 2013-11-06
  • 打赏
  • 举报
回复
这样的super()方法实现貌似太累赘吧,何况arguments.callee在严格模式下已经不支持. 附上我的一个建议吧

function Super() { }
Super.prototype.getName = function() {
    return "in Super";
};
function Lower() { }
Lower.prototype = new Super();
Lower.prototype.getName = function() {
    return "in Lower;" +  Super.prototype.getName.call(this);
};

BaronZ 2012-11-06
  • 打赏
  • 举报
回复
引用 20 楼 diky87688973 的回复:
引用 19 楼 axiheyhey 的回复: 引用 16 楼 diky87688973 的回复: 引用 14 楼 axiheyhey 的回复: 引用 13 楼 diky87688973 的回复: 引用 10 楼 axiheyhey 的回复: 心血来潮随手写的,肯定有bug,就没人拍砖吗。。 想法不错。 js实现面向对象编程模式,其中就需要定义关键字supe……
觉得这货很牛。。。。。。。。
峭沙 2011-12-18
  • 打赏
  • 举报
回复
好吧,我真心不知道说啥了。我发现我说的你听不懂,你说的我也听不懂。。
一個程序員 2011-12-18
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 axiheyhey 的回复:]

引用 16 楼 diky87688973 的回复:

引用 14 楼 axiheyhey 的回复:

引用 13 楼 diky87688973 的回复:

引用 10 楼 axiheyhey 的回复:

心血来潮随手写的,肯定有bug,就没人拍砖吗。。


想法不错。

js实现面向对象编程模式,其中就需要定义关键字super。

给你看一段代码:实现了super关……
[/Quote]

动用Object原型?貌似是你的代码动了原型,$super是我自定义的关键字。它是私有的。

定义全局$super?首先造成污染,而且super是每个类独有的,不能单列。原因是你不知道我何时调用方法

更没办法在我调用任意方法时,立即将super指到正确的对象上。

更更没办法知道我是在嵌套调用,

如:this.show(),show里面又有super.show(),里面又有this.hide(),hide中又用到super....

这些super调用会陷入嵌套调用里面,而却每个方法调用完毕后,又要归还super的指向。

你考虑过没?全局能做到?绑定到this上能做到?都不能。所以需要自定义个$super关键字,它跟类走,它永远指向当前类的父类。

这么说吧,你在java中如何使用super,那么这个$super就一样的用法。它的作用域不会超出方法之外。

这是我自己写的一个框架,名字叫Fan,扇子的意思。

其中OOP模块,全是参照java。包括super的概念和用法。

在IE里super是保留关键字,不可用。才叫$super。类的外部是访问不到的。

看了15楼仁兄的实现方式, 不用function做继承,将丧失很多东西,

1、失去instanceof派生对象类型鉴别

2、失去var创建私有属性,失去封装性

3、丧失new关键字构建对象

4、缺少super的概念,直接拿父类名称Cat.xxx来使用

这样的OOP模式,说实话,我不喜欢。

峭沙 2011-12-18
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 diky87688973 的回复:]

引用 14 楼 axiheyhey 的回复:

引用 13 楼 diky87688973 的回复:

引用 10 楼 axiheyhey 的回复:

心血来潮随手写的,肯定有bug,就没人拍砖吗。。


想法不错。

js实现面向对象编程模式,其中就需要定义关键字super。

给你看一段代码:实现了super关键字
JScript code

Fan.packa……
[/Quote]冒昧的问一句,$super是关键字吗。。应该不是吧?其实你的代码我似懂非懂,按我的理解,$super应该在构造器或方法内部缓存一个引用才对吧?
还有,如果用到call,大可不必动用Object原型,定义一个全局函数super即可。
峭沙 2011-12-18
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 rainsilence 的回复:]

JScript code
Object.prototype.mysuper = function(){
var caller = arguments.callee.caller,
name;
for(var i in this){
if(this[i] === caller){
name = i;
……
[/Quote]嗯,确实考虑不周,不过继承链的问题不难解决,只是动了Object原型这才是致命伤。你的方法因为时间原因只粗略的看了下,值得学习。不过用对象模拟类,instanceof是个问题。
一個程序員 2011-12-18
  • 打赏
  • 举报
回复
刚有个代码更正:
for (var m in $super) {
$super[m] instanceof Function && ($super[m] = proxy($super[m],$super));
}
漏了个$super没传入

另:实现super时,千万别让他和this有任何关联。不然,你会遇到无法处理多态中细节部分的尴尬。
一個程序員 2011-12-18
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 axiheyhey 的回复:]

引用 13 楼 diky87688973 的回复:

引用 10 楼 axiheyhey 的回复:

心血来潮随手写的,肯定有bug,就没人拍砖吗。。


想法不错。

js实现面向对象编程模式,其中就需要定义关键字super。

给你看一段代码:实现了super关键字
JScript code

Fan.package('Fan.test'); // 创建一个包
……
[/Quote]

例子只是片面的,只要你想用,完全可以:$super.initEvent()。

给你看的只是个例子。当你没有动手去实现一个super的时候,你不懂js与java的super的区别。

我的$super,无需定义,就像arguments,进入方法中,即可使用。

因为它是个关键字,而且是个仅在方法中才可访问到的特殊关键字。

它既是父类的构造方法,又是父类的实例对象。可以使用instanceof鉴别。

你知道java中new一个子类,其内存中也同时构造了父类对象么?

在深层次继承中,它还可以访问任意一层次的祖类对象,这点java并没提供。

例子随简单,至少你看懂了,对吧。本意就是让会java的人,能直接看懂js写的代码。

$super.initEvent.call(this);这句代码并不丑,你只是不喜欢这尾巴“call(this)”,js模拟多态,

肯定要用call或apply函数。即使不明写,那也将会隐式用到call。

如何隐式?

var proxy = function(fn, me){
return function(){
return fn.apply(me, arguments);
};
};


在构造父类时,将所有方法都处理一次:

for (var m in $super) {
$super[m] instanceof Function && ($super[m] = proxy($super[m]));
}


生产之后的$super再调用initEvent,只需$super.initEvent();

但是我并没这么做,why? 因为我觉得加个call(this)并不难看,而且,更容易看懂。

凡事没有必要过度封装。
rainsilence 2011-12-18
  • 打赏
  • 举报
回复
Object.prototype.mysuper = function(){
var caller = arguments.callee.caller,
name;
for(var i in this){
if(this[i] === caller){
name = i;
break;
}
}
__proto = this.__proto__ || this.constructor.prototype;
try{
return __proto[name].apply(this, arguments);
}catch(e){
alert(name + ' is undefined.');
}
}
function Animal(){
this.name = "animal";
this.setName = function(name){
this.name = name;
}
this.getName = function(){
return this.name;
}
}

function Cat(){
this.name = "cat";
this.setName = function(name){
this.name = name;
}
this.getName = function(){
return this.name + this.mysuper();
}
}

function Test(){
this.getName = function(){
return 'sub-' + this.mysuper();
}
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

Test.prototype = new Cat();
Test.prototype.constructor = Test;

var a = new Test();
alert(a.getName());


lz你看下上面这段代码。
如果单单只是实现一个父类,一个子类这样的。用this当然没什么问题。但是如果是父类,子类,进一步子类这样的继承链。用this就完蛋了。因为this只会指向最低端的类(因为会有对象冒充)。这也是为什么很多开源框架都用类似于静态变量的方法来实现super的根本原因。

另外,你的方法动了object的原型,不动原型的方法我的博客里有:
http://rainsilence.iteye.com/blog/1026530
峭沙 2011-12-18
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 diky87688973 的回复:]

引用 10 楼 axiheyhey 的回复:

心血来潮随手写的,肯定有bug,就没人拍砖吗。。


想法不错。

js实现面向对象编程模式,其中就需要定义关键字super。

给你看一段代码:实现了super关键字
JScript code

Fan.package('Fan.test'); // 创建一个包

// 创建类……
[/Quote]看了半天没看到$super的定义呢亲,而且从你的代码来看,$super仅仅只是一个对父类的引用而已,和java中的super相去甚远呢亲。。而且以 $super.initEvent.call(this);这种方式来用的话,是不是丑了点。。
一個程序員 2011-12-17
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 axiheyhey 的回复:]

心血来潮随手写的,肯定有bug,就没人拍砖吗。。
[/Quote]

想法不错。

js实现面向对象编程模式,其中就需要定义关键字super。

给你看一段代码:实现了super关键字

Fan.package('Fan.test'); // 创建一个包

// 创建类
Fan.clazz('Fan.test.A', function(){
var a = null; // 私有属性

this.aa = null; // 共有属性

// 构造方法
this.A = function(_a){
$super(); // 调用父类构造方法
a = _a;
};

this.init = function(){
alert2('A:init');
};
this.initEvent = function(){
alert2('A:initEvent');
this.show(1);
};
this.show = function(){
alert2('Fan.test.A');
};
});

// 创建类B,继承A
Fan.clazz('Fan.test.B', Fan.test.A, function(){
this.B = function(a, b){
$super(a); // 调用父类构造器,并传参数
};
this.init = function(){
alert2('B:init');
$super.init.call(this); // 调用父类方法
};
this._initEvent = function(){
alert2('B:initEvent');
$super.initEvent.call(this); // 调用父类方法
};
this.show = function(){
alert2('Fan.test.B');
};
});

// 创建C,继承B
Fan.clazz('Fan.test.C', Fan.test.B, function(){
// 当没有提供构造方法时,默认存在一个构造方法,且构造方法中只有一句代码$super();
//this.C = function(){
// $super();
//};
this.init = function(){
alert2('C:init');
this.initEvent();
};
this._initEvent = function(){
alert2('C:initEvent');
$super.getSuper().initEvent.call(this); // 调用父类的父类中的方法
};
this.show = function(p){
alert2('C:show ' + p);
if(p == 1){
$super.initEvent.call(this);
} else {
this.init();
}
};
});

Fan.clazz('Fan.test.D', Fan.test.C, function(){
this.D = function(){
$super();
};
this.init = function(){
alert2('D:init');
$super.init.call(this);
};
this._initEvent = function(){
alert2('D:initEvent');
$super.initEvent.call(this);
};
});

// 检测
a = new Fan.test.D();
a.show();

// 类型检测
a instanceof Fan.test.D // true
a instanceof Fan.test.C // true
a instanceof Fan.test.B // true
a instanceof Fan.test.A // true
a instanceof a.getClass() // true
a instanceof a.getClass().superClass // true
a instanceof a.getClass().superClass.superClass // true
a instanceof Object // true

在a的实例方法中 :$super instanceof this.getClass().superClass // true


峭沙 2011-12-17
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 sohighthesky 的回复:]

Object不能随便拓展的吧?
[/Quote]话是这样说,但是像这种很基础的扩展,不动Object有别的办法吗
sohighthesky 2011-12-17
  • 打赏
  • 举报
回复
Object不能随便拓展的吧?
峭沙 2011-12-17
  • 打赏
  • 举报
回复
心血来潮随手写的,肯定有bug,就没人拍砖吗。。
-晴天 2011-12-15
  • 打赏
  • 举报
回复
我也支持一下,还学习一下,看是不是会被删...
  • 打赏
  • 举报
回复
好像N年前就看过有人写过这个supper。
三石-gary 2011-12-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 axiheyhey 的回复:]

引用 3 楼 zsx841021 的回复:

我心碎了。。。NMD 支持下怎么了。。。又tmd乱删回复。。
你们是肿么了,怎么回复被删了,而且删得如此之快。。
[/Quote]
我就打了3个字。。:支持下。。哎对这论坛无语了
峭沙 2011-12-14
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 zsx841021 的回复:]

我心碎了。。。NMD 支持下怎么了。。。又tmd乱删回复。。
[/Quote]你们是肿么了,怎么回复被删了,而且删得如此之快。。
峭沙 2011-12-14
  • 打赏
  • 举报
回复
简单的加个异常处理
		Object.prototype.mysuper = function(){
var caller = arguments.callee.caller,
name;
for(var i in this){
if(this[i] === caller){
name = i;
break;
}
}
__proto = this.__proto__ || this.constructor.prototype;
try{
return __proto[name].apply(this, arguments);
}catch(e){
alert(name + ' is undefined.');
}
}
function Class(){
this.name = "class";
this.setName = function(name){
this.name = name;
}
this.getName = function(){
return this.name;
}
}
function Test(){
this.getName = function(){
return 'sub-' + this.mysuper();
}
}
Test.prototype = new Class();
Test.prototype.constructor = Test;

var a = new Test();
alert(a.getName());
三石-gary 2011-12-14
  • 打赏
  • 举报
回复
我心碎了。。。NMD 支持下怎么了。。。又tmd乱删回复。。

87,997

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧