怎样在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. Protobuf从安装到配置整理帖 --转

    新做的Mini项目计划使用Google的Protobuf来做,关于Protobuf是什么玩意能干什么请自己去看这里:http://code.google.com/p/protobuf/ 这里讲一下安装 ...

  2. c语言结构体排序示例

    设计性实验编程实现对学生成绩表的相关信息排序.实验要求:⑴ 建立一个由n个学生的考试成绩表,每条信息由学号.姓名和分数组成.⑵ 按学号排序,并输出排序结果.⑶ 按分数排序,分数相同的则按学号有序,并输 ...

  3. A fatal error has been detected by the Java Runtime Environment:

    在Eclipse中运行项目 遇到如下错误: ## A fatal error has been detected by the Java Runtime Environment:## EXCEPTIO ...

  4. jquery去除字符串首尾空格的方法:$.trim()

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. REST和JAX-RS相关知识介绍

    REST REpresentational State Transfer:代表性状态传输.具象状态传输 REST定义了应该如何正确地使用Web标准,例如HTTP和URI.REST并非标准,而是一种开发 ...

  6. DB Query Analyzer 5.04 is released, 63 articles concerned have been published

    DB Query Analyzer 5.04 is released, 63 articles concerned have been published DB QueryAnalyzer is pr ...

  7. C# in Depth阅读笔记3:C#3特性

    1.隐式类型 var a=new Dictionary<string ,list<person>>();可以简化代码,增强可读性. 2.简化初始化 (1)设置简单属性 Pers ...

  8. js/jquery获取浏览器窗口可视区域高度和宽度以及滚动条高度实现代码

    获取浏览器窗口的可视区域高度和宽度,滚动条高度有需要的朋友可参考一下.IE中,浏览器显示窗口大小只能以下获取: 代码如下复制代码 代码如下: document.body.offsetWidth doc ...

  9. unix网络编程笔记

    TCP连接状态转换图:

  10. ubuntu中Mysql常用命令整理

    启动mysql服务sudo /etc/init.d/mysql start 关闭mysql服务sudo /etc/init.d/mysql stop