怎样在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. mysql memcache

    http://blog.csdn.net/newjueqi/article/details/8350643

  2. libc++abi.dylib handler threw exception

    在iOS开发时,有时候遇到libc++abi.dylib handler threw exception这样的异常,  虽然在断点出加上了All Exceptions,也断到相应的代码了,但是没打印对 ...

  3. 多线程编程 - GCD(转)

    原文:http://blog.csdn.net/q199109106q/article/details/8566300 一.简介 在iOS所有实现多线程的方案中,GCD应该是最有魅力的,因为GCD本身 ...

  4. 将类数组对象(array-like object)转化为数组对象(Array object)

    用法:Array.prototype.slice.call(array-like object) // 创建一个类数组对象 var alo = {0:"a", 1:"b& ...

  5. OC弱语法

    OC是在运行过程中才会检测对象有没有实现相应的方法,所有编译过程只给出警告:可能找不到对应方法: 如果程序在运行过程中出错,就会出现程序闪退:     类方法:类可以直接调用的方法,相当于java中的 ...

  6. shell 比较

    整数比较 -eq 等于,如:if [ "$a" -eq "$b" ] -ne 不等于,如:if [ "$a" -ne "$b&qu ...

  7. 用正则表达式替换内容 php

    以前做一个项目,就是有一个问答的页面,比如说在回答或者提问的内容中插入表情.写到内容里的是表情图片的名字(而且是不带后缀的,比如:f_002.png)表情包放在项目里,我需要在取除内容的时候将里面的表 ...

  8. html combobox select控件设置默认选项

    就想找个设置html combobox或者select默认选项的代码,百度搜了半小时不知所云的内容,其实很简单,代码如下 js的方式: var index = 你的下标 getElementById( ...

  9. 关于 MyBatis MyBatis-Spring Jdbc 批量插入的各种比较分析

    因为目前SME项目中编写了一套蜘蛛爬虫程序,所以导致插入数据库的数据量剧增.就项目中使用到的3种DB插入方式进行了一个Demo分析: 具体代码如下: 1: MyBatis 开启Batch方式,最普通的 ...

  10. 关于NGINX下开启PHP-FPM 输出PHP错误日志的设置(已解决)

    最近在本地搭建的LNMP的开发环境.为了开发的时候不影响前端的正常开发就屏蔽的PHP里面php.ini中的一些错误提示.但是这样一来,就影响到了后端开发的一些问题比如不能及时调试开发中的一些问题. n ...