今天要讨论的主题是下面3种方案的对比:
前提:
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的继承有了更深一步的了解!
分享到:
相关推荐
本文将深入探讨JavaScript中的面向对象编程,特别是关于构造函数的继承。 首先,我们来理解构造函数在JavaScript面向对象编程中的作用。构造函数是一种特殊类型的函数,用于初始化新创建的对象。例如,我们可以定义...
理解`instanceof`的工作原理,我们需要深入到JavaScript的原型链(prototype chain)和`GetValue`方法。根据ECMAScript-262 Edition 3标准,`instanceof`运算符的工作原理如下: 1. 评估`RelationalExpression`(即...
本文将深入探讨JavaScript中的面向对象编程,特别是构造函数的继承机制。 首先,我们来看构造函数的继承。构造函数在JavaScript中用于创建特定类型的对象。例如,`Animal`和`Cat`是两个构造函数,分别代表“动物”...
这门“JavaScript深度剖析”课程显然旨在帮助开发者深入理解其内部机制,提升技能水平。通过下载的课件,学习者可以系统地掌握JavaScript的各种关键概念和高级特性。 首先,JavaScript是一种解释型的、基于原型的...
在这个压缩包中,可能包含了一系列章节或教程,逐一剖析JavaScript的关键概念和技术。 首先,我们要了解JavaScript的基础。JavaScript是一种解释型的、基于原型的、动态类型的编程语言。它的主要特点是弱类型和事件...
这个名为"JavaScript深度剖析.zip"的压缩包文件显然包含了关于JavaScript深入学习的教学资源,可能包括讲义、代码示例、练习题和解剖案例等,旨在帮助用户提升JavaScript编程技能。 JavaScript的核心知识点涵盖了...
JavaScript作用域是编程中至关重要的概念,尤其是在JavaScript这种动态类型的脚本语言中。它规定了变量、函数以及其它标识符的可见...这份12页的PDF文档将详细剖析这些关键点,是JavaScript学习者不可多得的参考资料。
JavaScript 深度剖析 JavaScript 是一种广泛应用于Web开发的轻量级编程语言,由Netscape公司的Brendan Eich在1995年设计,最初被命名为LiveScript。JavaScript 不是Java的子集,尽管名字相似,两者在设计哲学和语法...
在对象和原型链方面,《悟透JavaScript》深入剖析了JavaScript的面向对象特性,包括构造函数、原型、原型链、继承机制。这部分内容对于理解和编写可维护的代码至关重要,因为JavaScript的面向对象模型与传统的类继承...
《Pro JavaScript Design Patterns》是一本不可多得的好书,它不仅全面介绍了JavaScript设计模式的相关知识,还深入剖析了面向对象编程的核心原理和技术细节。对于想要提升自己JavaScript编程水平的开发者来说,这...
本书“JavaScript核心技术开发解密”由阳波撰写,旨在深入剖析JavaScript的核心技术,帮助读者掌握这门语言的精髓。书中包含232页的内容,覆盖了JavaScript的各个方面,为开发者提供了宝贵的资源和实践指导。 ...
这本书深入剖析了JavaScript的本质,包括对象、函数、继承和数组等多个关键概念,对于深化对JavaScript语言的理解非常有帮助。反复阅读可以不断巩固知识,提高编程水平。 在学习过程中,不断实践和反思是提升的关键...
- **原型链**:深入理解JavaScript中的原型链机制,明白对象继承的原理。 - **this关键字**:掌握this在不同上下文中指向的对象,理解其作用于函数调用模式的变化。 #### 3. 高级特性 - **异步编程**:学习事件循环...