锁定老帖子 主题:深入剖析Javascript之继承
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-04-11
前提: var m1 = function(){}; var m2 = function(){}; 要对比的3种方案是: 1>Object.extend( m1.prototype, m2.prototype ); 2>m1.prototype = m2.prototype; 3>m1.prototype = new m2(); 下面对各种方案先预先给予说明: 1>第一种方案是将m2.prototype该对象中所有成员拷贝(覆盖)到m1.prototype对象中。 看代码: var m1 = function(){}; var m2 = function(){}; var o2 = new m2(); o2.name = 'qk'; m2.prototype.print = function() { alert( this.name ); } Object.extend( m1.prototype, m2.prototype ); 到此,我们可以想象,m2.prototype中的成员变量print已经拷贝到m1.prototype中,即,凡m1对象便拥有print成员。假如我们试图创建m1的对象, var o1 = new m1(); 则我们可以调用o1.print();但由于m1对象中不存在name属性,故会是undefined。问题在哪?是因为m2.prototype对象的成员中包含了m2的实例变量name,这种设计方案是不合理的(这里只是为了演示所用,现实中是不会出现类似的代码的,下同)。 2>第二种方案是将m1.prototype对象的指针指向m2.prototype的内存地址。或m1.prototype对象只是m2.prototype对象的一个引用。试图改变m2.prototype内存地址后不会影响m1.prototype对象成员的变化。看代码: var m1 = function(){}; var m2 = function(){}; var o2 = new m2(); o2.name = 'qk'; m2.prototype.print = function() { alert( this.name ); } m1.prototype = m2.prototype; // 改变m2.prototype m2.prototype = {0:0}; // 打印 var o1 = new m1(); for( var key in o1 ) { alert( key + '=>' + o1[ key ] ); } 不过,如果对m2.prototype对象的成员进行增加或删除,m1.prototype就会改变。看代码: var m1 = function(){}; var m2 = function(){}; var o2 = new m2(); o2.name = 'qk'; m2.prototype.print = function() { alert( this.name ); } m1.prototype = m2.prototype; // 增加m2.prototype对象的成员。 m2.prototype[0] = 0; // 打印 var o1 = new m1(); for( var key in o1 ) { alert( key + '=>' + o1[ key ] ); } 3>第二种方案是让m1.prototype链式继承m2.prototype的所有成员。即m1.prototype继承m2.prototype,m2.prototype继承Object.prototype.它于第二种方案的不同是,第二种方案中,m1.prototype只是m2.prototype对象的一个引用。只有增加或删除m2.prototype成员才会引起m1.prototype成员的变化。它于第一种方案的不同是,第一种方案中,m1.prototype成员只会增加,不会减少。而这里是链式继承。看代码: var m1 = function(){}; var m2 = function(){}; var o2 = new m2(); o2.name = 'qk'; m2.prototype.print = function() { alert( this.name ); } m1.prototype = new m2(); // 打印 var o1 = new m1(); for( var key in o1 ) { alert( key + '=>' + o1[ key ] ); } 此时,o1对象访问属性的顺序是: m1.prototype对象成员 > m2的实例变量 > m2.prototype对象成员 > m1的的实例变量 好了,介绍完这3种“继承”后,希望大家对javascript的prototype的继承有了更深一步的了解! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-04-12
分析得挺不错的,最好能结合流行的js library进行分析 如 prototype ext moonkit module等
|
|
返回顶楼 | |
发表时间:2007-04-12
m2.prototype = Object.extend(new m1, m2.prototype ); m1是父类,m2是子类 prototype中继承的代码: Object.extend = function(destination, source) { for (property in source) { destination[property] = source[property]; } return destination; } |
|
返回顶楼 | |
发表时间:2007-05-16
Object.extend = function(destination, source) {}
|
|
返回顶楼 | |
发表时间:2007-05-16
其实,实用Prototype框架的话,用Class.create()来创建类使用他的风格,我觉得对继承的支持就足够了,而且可以通过mixin实现多继承。比如,我有一个基类A:
js 代码
然后,我有一个继承自A的子类B, js 代码
这样就实现了类继承。注意一个技巧,我们将基类的构造方法抽取出来用_init实现,就是为了在子类中覆盖initialize而又可以初始化父类的成员。接下来,我们可以这么调用: js 代码
至于mixin,其实很简单,等我把我的另一篇文章写完,会详细介绍其中的一些技巧和方法的: www.iteye.com/topic/79869 |
|
返回顶楼 | |
发表时间:2007-08-02
var m1 = function(){};
var m2 = function(){}; var o2 = new m2(); o2.name = 'qk'; m2.prototype.print = function() { alert( this.name ); } m1.prototype = m2.prototype; // 改变m2.prototype,内存地址改变,但m1指向原来的地址 m2.prototype = {0:0}; // 增加m2.prototype对象的成员。 m2.prototype[1] = 1; // 打印 var o1 = new m1(); for( var key in o1 ) { alert( key + '=>' + o1[ key ] ); } 为什么只打印print=>function() { alert( this.name ); } |
|
返回顶楼 | |
发表时间:2007-08-02
哦,对了,m2指向的地址已经改了,所以再增加成员也没用,
那减少成员怎么写? |
|
返回顶楼 | |
发表时间:2007-08-02
var m1 = function(){};
var m2 = function(){}; var o2 = new m2(); o2.name = 'qk'; m2.prototype.print = function() { alert( this.name ); } m1.prototype = new m2(); m1.prototype.i = 'i'; // 打印 var o1 = new m1(); o1.love='love'; for( var key in o1 ) { alert( key + '=>' + o1[ key ] ); } 怎么看不到m2的实例变量? |
|
返回顶楼 | |
发表时间:2007-08-02
哪位高手能研究一下MapEasy API。
|
|
返回顶楼 | |
发表时间:2007-08-03
你说的前两种根本构不成继承。都只是复制或者共享了原型。这样的m1和m2的实例只能说是兄弟,不能说有继承。所以方法一和方法二只能说是一种代码复用的手段,而谈不上继承。
|
|
返回顶楼 | |