怎样在JavaScript中实现简单的继承? 

以下的样例将创建一个雇员类Employee,它从Person继承了原型prototype中的全部属性。

function Employee(name, sex, employeeID) {
this.name = name;
this.sex = sex;
this.employeeID = employeeID;
}
// 将Employee的原型指向Person的一个实例
// 由于Person的实例能够调用Person原型中的方法, 所以Employee的实例也能够调用Person原型中的全部属性。
Employee.prototype = new Person();
Employee.prototype.getEmployeeID = function() {
return this.employeeID;
};
var zhang = new Employee("ZhangSan", "man", "1234");
console.log(zhang.getName()); // "ZhangSan

上面关于继承的实现非常粗糙,而且存在非常多问题:

  • 在创建Employee构造函数和原型(以后简称类)时,就对Person进行了实例化,这是不合适的。
  • Employee的构造函数没法调用父类Person的构造函数,导致在Employee构造函数中对name和sex属性的反复赋值。
  • Employee中的函数会覆盖Person中的同名函数,没有重载的机制(和上一条是一个类型的问题)。
  • 创建JavaScript类的语法过于零散,不如C#/Java中的语法优雅。
  • 实现中有constructor属性的指向错误。

正由于JavaScript本身没有完整的类和继承的实现,而且我们也看到通过手工实现的方式存在非常多问题, 因此对于这个富有挑战性的任务网上已经有非常多实现了:

这篇文章将会给出一个可行的实例代码详细分析这些实现,终于达到对JavaScript中怎样实现类和继承,希望对你理解JavaScript有一定的帮助。

( function() {
jClass = function() {
};
// 当前是否处于创建类的阶段
var initializing = false;
jClass.extend = function( prop ) {
var baseClass = null;
// 假设调用当前函数的对象(这里是函数)不是Class,则是父类
if ( this !== jClass ) {
baseClass = this;
}
// 本次调用所创建的类(构造函数)
var jConstructor = function() {
// 假设当前处于实例化类的阶段,则调用init原型函数
if ( !initializing ) {
// 假设父类存在,则实例对象的baseprototype指向父类的原型
// 这就提供了在实例对象中调用父类方法的途径
if ( baseClass ) {
this._superprototype = baseClass.prototype;
}
this.init.apply( this, arguments );
}
}
// 假设此类须要从其他类扩展
if ( baseClass ) {
initializing = true;
jConstructor.prototype = new baseClass();
jConstructor.prototype.constructor = jConstructor;
initializing = false;
}
// 新创建的类自己主动附加extend函数
jConstructor.extend = arguments.callee; // 覆盖父类的同名函数
for ( var name in prop ) {
if ( prop.hasOwnProperty( name ) ) {
// 假设此类继承自父类baseClass,而且父类原型中存在同名函数name
if ( baseClass &&
typeof ( prop[name] ) === "function" &&
typeof ( jConstructor.prototype[name] ) === "function" &&
/\b_super\b/.test( prop[name] ) ) {
// 重定义函数name -
// 首先在函数上下文设置this._super指向父类原型中的同名函数
// 然后调用函数prop[name],返回函数结果
// 注意:这里的自运行函数创建了一个上下文,这个上下文返回还有一个函数,
// 此函数中能够应用此上下文中的变量,这就是闭包(Closure)。
// 这是JavaScript框架开发中经常使用的技巧。
jConstructor.prototype[name] = ( function( name, fn ) {
return function() {
this._super = baseClass.prototype[name];
return fn.apply( this, arguments );
};
} )( name, prop[name] );
} else {
jConstructor.prototype[name] = prop[name];
}
}
}
return jConstructor;
};
} )(); // Demo
var Person = jClass.extend( {
init: function( name ) {
this.name = name;
},
getName: function( prefix ) {
return prefix + this.name;
}
} );
var Employee = Person.extend( {
init: function( name, employeeID ) {
// 调用父类的方法
this._super( name );
this.employeeID = employeeID;
},
getEmployeeIDName: function() {
// 注意:我们还能够通过这样的方式调用父类中的其他函数
var name = this._superprototype.getName.call( this, "Employee name: " );
return name + ", Employee ID: " + this.employeeID;
},
getName: function() {
// 调用父类的方法
return this._super( "Employee name: " );
}
} ); var zhang = new Employee( "ZhangSan", "1234" );
console.log( zhang.getName( ) ); // "Employee name: ZhangSan"
console.log( zhang.getEmployeeIDName() ); // "Employee name: ZhangSan, Employee ID: 1234"

JavaScript继承的实现的更多相关文章

  1. javascript继承的三种模式

    javascript继承一般有三种模式:组合继承,原型式继承和寄生式继承: 1组合继承:javascript最为广泛的继承方式通过原型链实现对原型属性和方法的继承,通过构造函数实现对实例属性的继承,同 ...

  2. javascript继承机制的设计思想(ryf)

    我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...

  3. 【读书笔记】javascript 继承

    在JavaScript中继承不像C#那么直接,C#中子类继承父类之后马上获得了父类的属性和方法,但JavaScript需要分步进行. 让Brid 继承 Animal,并扩展自己fly的方法. func ...

  4. 图解JavaScript 继承

    JavaScript作为一个面向对象语言,可以实现继承是必不可少的,但是由于本身并没有类的概念(不知道这样说是否严谨,但在js中一切都类皆是对象模拟)所以在JavaScript中的继承也区别于其他的面 ...

  5. JavaScript强化教程——Cocos2d-JS中JavaScript继承

    javaScript语言本身没有提供类,没有其它语言的类继承机制,它的继承是通过对象的原型实现的,但这不能满足Cocos2d-JS引擎的要求.由于Cocos2d-JS引擎是从Cocos2d-x演变而来 ...

  6. [原创]JavaScript继承详解

    原文链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++. ...

  7. javascript继承(六)—实现多继承

    在上一篇javascript继承—prototype最优两种继承(空函数和循环拷贝)(3) ,介绍了js较完美继承的两种实现方案,那么下面来探讨一下js里是否有多继承,如何实现多继承.在这里可以看看j ...

  8. javascript继承(五)—prototype最优两种继承(空函数和循环拷贝)

    一.利用空函数实现继承 参考了文章javascript继承—prototype属性介绍(2) 中叶小钗的评论,对这篇文章中的方案二利用一个空函数进行修改,可以解决创建子类对象时,父类实例化的过程中特权 ...

  9. javascript继承(四)—prototype属性介绍

    js里每一个function都有一个prototype属性,而每一个实例都有constructor属性,并且每一个function的prototype都有一个constructor属性,这个属性会指向 ...

  10. 【JavaScript】重温Javascript继承机制

    上段时间,团队内部有过好几次给力的分享,这里对西风师傅分享的继承机制稍作整理一下,适当加了些口语化的描述,留作备案. 一.讲个故事吧 澄清在先,Java和Javascript是雷锋和雷峰塔的关系.Ja ...

随机推荐

  1. Linux Syslog

    http://blog.chinaunix.net/uid-677314-id-164215.html http://blog.chinaunix.net/uid-24708340-id-397132 ...

  2. kernal linear regression

  3. Debug, Release区别

    Debug, Release区别 Debug附加了很多调试信息,主要用于调试,所以文件大 Release就是经过优化的版本,去除了调试信息,进行了代码优化,所以文件较小,同时速度要快于Debug De ...

  4. Objective-C 内存管理之 _ARC

    内存管理之 ARC 和 自己主动释放池 一.ARC 中的变量全部权修饰符 变量修饰符,主要用来标识对象的生命周期.在手动内存管理方式中没有这些概念. ARC 环境下变量全部权修饰符主要有以下几个: _ ...

  5. Unable to open ...\tools\capture\allegro.cfg for reading

    采用Capture CIS 当生成网表.误: Unable to open ...\tools\capture\allegro.cfg for reading. Please correct the ...

  6. JavaScript字符串插入、删除、替换函数

    JavaScript字符串插入.删除.替换函数 说明: 以下函数中前两个函数取出查找字符串的前一部分和后一部分,以用于其他函数.注意,调用一次 replaceString(mainStr,search ...

  7. 一台服务器同时搭建IIS和WAMP,利用WAMP 80端口转发

    打开wamp 里面的 httpd.conf 文件,找到以下四个语句,取消注释 #LoadModule proxy_module modules/mod_proxy.so -->LoadModul ...

  8. 记录下url拼接的多条件筛选js

    本着为提高工作效率百度或者google这些代码发现拿过来的都不好用,然后自己写了个,写的一般但记录下以后再优化 <html> <head> <script> $(f ...

  9. BOOST CHRONO steadycolock::now分析

    一直觉得boost的时间库不是很好用,当然,也有可能是我没有深入理解,所以,把代码弄出来看看或许要好些,时间处理中,取当前时间真的是太常见,而boost中各种clock又区分不清楚,然而,代码能说明一 ...

  10. Sublime Text3 插件安装教程

    链接地址:http://jingyan.baidu.com/article/4d58d541caeeaa9dd4e9c093.html