怎样在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. Delphi使用Windows API函数AnimateWindow实现窗体特效

    {**********************************************************************API函数 AnimateWindow 使用:函数功能:窗 ...

  2. Android 禁止软键盘自动弹出

    Android系统对EditText这个控件有监听功能,如果某个Activity中含有该控件,就会自动弹出软键盘让你输入,这个看似人性化的方案有 时候并不被用户喜欢的,所以在有些情况下要禁用该功能.这 ...

  3. 一个js爬虫

    1. 第一个demo 2. configs详解——之成员 3. configs详解——之field 4. configs详解——之site, page和console 5. configs详解——之回 ...

  4. U-boot中实现Yaffs2+HwEcc

    经过老手的指点,要实现Yaffs2+HwEcc,重点在于chip->ops.mode由MTD_OOB_RAW到MTD_OOB_AUTO.经过几天的筹备,今天要对其下手了.为了真实展现分析移植过程 ...

  5. CSS 垂直居中的5种实现方法

    利用 CSS 来实现对象的垂直居中有许多不同的方法,比较难的是选择那个正确的方法.我下面说明一下我看到的好的方法和怎么来创建一个好的居中网站.         使用 CSS 实现垂直居中并不容易.有些 ...

  6. 兼容所有浏览器的CSS3圆角

    兼容所有浏览器的CSS3圆角      解决CSS3圆角兼容所有浏览器的方法.本文提到了一种很不错的实现跨浏览器圆角的解决方案,但是说的不够全面,前端观察最近将整理更多更全面的资源给大家,敬请期待. ...

  7. SQL中去除某字段中的某个字符语法

    update S_ENTERPRISE set DAY_PROCESS=replace(DAY_PROCESS,'吨','') where DAY_PROCESS like '%吨%'

  8. android的Log日志打印管理工具类(一)

    android的Log日志的打印管理工具类: package com.gzcivil.utils; import android.util.Log; /** * 日志打印管理 * * @author ...

  9. EJB QI查询

    EO.PNAME like ?1 OR  EO.PNAME like ?2";      Query query = entityManager.createNativeQuery(quer ...

  10. C++_内部类

    C++ 内部类和外部类之间的相互调用