论坛首页 Web前端技术论坛

危险的prototype, 你实现了继承吗?

浏览 5805 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-12-19  
含有私有变量的类如果被另一个类用prototype模拟"继承",将产生私有变量共享威胁:

function f1(){
  var p = {};
 this.getP = function(){
   return p;
 };
}
function f2(){}
f2.prototype = new f1();

var f1_ins_1 = new f1();
var f1_ins_2 = new f1();
alert(f1_ins_1.getP() == f1_ins_2.getP());// ->false

var f2_ins_1 = new f2();
var f2_ins_2 = new f2();
alert(f2_ins_1.getP() == f2_ins_2.getP());//-> true

//f2_ins_1 与 f2_ins_2共享 f1私有变量p == 我一个下午的bug测试 *_*


建议:含私有变量的类加 final 标识,防止被prototype。
   发表时间:2007-12-20  

兄弟,这不是继承的错,是因为f2的prototype引用的是f1的一个实例,所以f2的实例在调用getP时,获得是同一个闭包内的P。

这种构造函数的定义明显就是错误的。构造函数只是用来初始化类成员,也从来不需要定义局部变量,也从来都不定义类方法。且,即使按照你的这样的定义,难道不知道子类需要在构造函数中,调用父类的构造函数吗?比如

js 代码
  1. function f2() {   
  2.    f1.apply(this,arguemnts);   
  3. }   

这样,就消除了你说的变量冲突问题。也对于oo来说,也是合理的做法。

0 请登录后投票
   发表时间:2007-12-20  
什么玩艺呀,f2的prototype对象是在构造之前被指定为了new f1当然你再怎么new f2他的f1 prototype也是原来那个呀,就是这么简单不是什么bug
0 请登录后投票
   发表时间:2007-12-20  
prototype的共享的问题确实容易把人搞晕。
我的建议是:
prototype上只能放置无状态元素,比如,没有私有闭包的函数,原始类型。

对于构造器中申明的成员函数。普通对象,数组对象等有状态元素作为成员时更是要特别小心。
0 请登录后投票
   发表时间:2007-12-20  
在子类f2,f3里加f1.apply 可以解决,但 如果f1 又继承自另一个父类f0, 那么 f2,f3的实例 还是存在 共享f0 私有变量的 威胁


function f0(){
  var p0 = {};  
this.getP0 = function(){  
   return p0;  
};  
}
f1.prototype = new f0();
alert((f3_ins_1.getP0() == f3_ins_2.getP0()));//-> true
0 请登录后投票
   发表时间:2007-12-20  
威胁个什吗玩艺,根本就是对象是这么实现的,一个对象当然只有一个函数指针一套scope chain,去学习js语法后再来这里讨论
0 请登录后投票
   发表时间:2007-12-20  
afcn0 写道
威胁个什吗玩艺,根本就是对象是这么实现的,一个对象当然只有一个函数指针一套scope chain,去学习js语法后再来这里讨论
呵呵,js的语法俺可能还真没学通!不过兄弟可否推荐个继承的函数,当出现多重继承时(也许我们还不知道已经是多重继承了),又不会存在共享私有变量(在父类的父类中)的问题。
0 请登录后投票
   发表时间:2007-12-20  
多重继承本来就是危险的,js本身也不是class-based的,要多重继承干吗?人家大名鼎鼎的java都抛弃了多继承。js还要执着干吗??另外,你说的也根本不是多重继承。只是条继承链而已。js以object-based的特性,实现的是prototype链的“继承”关系。另外再次声明,在构造函数内,只要你不去定义类方法,完全不存在这种威胁(因为根本不会存在闭包)。
0 请登录后投票
   发表时间:2007-12-20  
俺不懂继承,不知道是什吗玩意
0 请登录后投票
   发表时间:2007-12-20  
function f1(){  
  var p = {};  
this.getP = function(){  
   return p;  
};  
}  
function f2(){}  
f2.prototype = new f1();  //这里的f1我用a表示
 
var f1_ins_1 = new f1();   //这里的f1我用b表示
var f1_ins_2 = new f1();   //这里的f1我用c表示
//b!=c,这没有话说,相信大家都没有什么意见
alert(f1_ins_1.getP() == f1_ins_2.getP());// ->false  
//请看清楚a,f2.prototype = new f1(); //这是a
var f2_ins_1 = new f2();   //f2_ins_1.getP()==a.getP();
var f2_ins_2 = new f2();   //f2_ins_2.getP()==a.getP();
//所以返回值是TRUE
alert(f2_ins_1.getP() == f2_ins_2.getP());//-> true

//PS:不知道你们看明白没有,呵呵。。 prototype,小心使用
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics