此网站为郑州seo技术博客网站,欢迎加好友互相探讨!
当前位置:郑州SEO博客 > HTML技巧 > 正文

JavaScript的继承机制

11-22 HTML技巧

JavaScript中的继承与其他语言中基于类的继承有所差异,但又有异曲同工之妙,典型的C、Java乃至PHP中的继承是基于基类(或者说父类),涉及到类(class)的概念,子类继承基类,实例化子类后的对象即可使用继承自基类的方法(method)和属性( property),继承有关的理论中又有单继承、多继承以及覆盖(又称:重写 ,英文override)、重载(overload)、多态(polymorphism)的概念,学院派哪套就不多吧唧了~

从传统意义上来说,JavaScript并不真正具有类;除了不存在类,在ECMA-262标准中根本没有出现“类”这个词。JavaScript标准中倒是规定了“Object定义”有关的内容,而这里的“Object定义”逻辑上等价于其他程序设计语言中的类,所以JavaScript中的继承实质来讲就是:多个Object对象定义中实现其中某一个定义的对象Object在实例化后的对象内的属性和方法可从其他一个或多个定义的Object中继承的过程;更白话一些来说就是一个Object对象从另外一个或多个Object对象获得属性、方法的过程。在ECMA-262标准中JavaScript中的继承机制也不是明确规定的,所以JavaScript中的继承也是一种模仿实现,是那么个意思就够了,无需牵强附会必须要用C、Java那一套来理论。“Object定义”即“对象定义”是定义一个Object对象的过程,这Object先被定义,后被实例化才能生成实实在在的对象。

this关键字

在 ECMAScript 中,要掌握的最重要的概念之一是关键字this的用法,它用在对象的方法中。关键字this总是指向调用该方法的对象。

// this关键字 var oCar = new Object; oCar.color = "red"; oCar.showColor = function() { console.log(this.color); }; oCar.showColor();

利用this关键字的这种总是指向调用该方法的对象的特性可以实现一个或多个对象的继承。

对象冒充

this关键字总是指向调用该方法的对象的特性,可以在多个对象定义中悄然改变this指向从而达到一个或多个对象中的属性和方法被另外一个对象继承的目的。

传统方式 // ClassA 基类的构造函数 function ClassA(sColor) { this.color = sColor; this.sayColor = function () { console.log(this.color); }; } // ClassB 子类的构造函数 function ClassB(sColor, sName) { // 为ClassB新增一个newMethod属性值,赋值ClassA构造函数指向的指针(引用) this.newMethod = ClassA; // 执行newMethod属性值指向的函数方法即ClassA--- ClassA作为常规函数来执行而不是作为构造函数 // 此处不是用的new语法,而是作为一个普通函数执行,且是在this指定的对象下执行的 // 那么newMethod内部的this值指向的对象就变成了ClassB所实例化的对象(而不是ClassA) // 这个时候newMethod方法执行完毕就相当于为这个实例化ClassB产生的对象定义了color属性和sayColor方法 // 从而实现了ClassB继承ClassA的方法和属性的功能 this.newMethod(sColor); // 显式删除ClassB的newMethod属性值,ClassB实例化后的对象就无法使用该属性值,从而避免一些问题 delete this.newMethod; // 为ClassB定义新属性和新方法,没有什么好说的 this.name = sName; this.sayName = function () { console.log(this.name); }; } var objA = new ClassA("蓝色"); var objB = new ClassB("红色", "Jea杨"); objA.sayColor(); //输出 "蓝色" objB.sayColor(); //输出 "红色"---ClassB中并没有显式的定义sayColor方法,继承而来 objB.sayName(); //输出 "Jea杨"

上述示例代码中,ClassB仅继承了ClassA,属于单继承;经过适当的改动也是可以实现多继承的。如果存在两个类 ClassX 和 ClassY,ClassZ 想继承这两个类,在ClassZ构造函数定义时如法炮制即可完成多继承,如下:

function ClassX() { // code ClassX定义省略 } function ClassY() { // code ClassY定义省略 } function ClassZ() { this.newMethod = ClassX; this.newMethod(); delete this.newMethod; this.newMethod = ClassY; this.newMethod(); delete this.newMethod; } call方法可手动指定this指向的方式

基本原理依然是利用this关键词的一些特性,而体现在call方法上则是Function对象的call方法的第一个参数可以用来指定被执行函数执行时的this指针。call方法的调用形式是:fun.call(thisArg[, arg1[, arg2[, ...]]]),其中thisArg参数为fun函数执行时指定的this值,其他1个或多个可选参数则为fun函数执行时依次传递的实参。

// ClassA 基类的构造函数 function ClassA(sColor) { this.color = sColor; this.sayColor = function () { console.log(this.color); }; } // ClassB子类 function ClassB(sColor, sName) { // 原先的老旧方式 /* this.newMethod = ClassA; this.newMethod(color); delete this.newMethod; */ // 利用call方法实现继承 // 利用ClassA的call特性,将ClassB实例化后的对象也就是this指向了ClassA // 执行了ClassA也就为ClassB实例化后的对象定义了color属性和sayColor方法 // 从而实现了ClassB继承ClassA的方法和属性的功能 ClassA.call(this, sColor); this.name = sName; this.sayName = function () { console.log(this.name); }; } var objA = new ClassA("蓝色"); var objB = new ClassB("红色", "Jea杨"); objA.sayColor(); //输出 "蓝色" objB.sayColor(); //输出 "红色"---ClassB中并没有显式的定义sayColor方法,继承而来 objB.sayName(); //输出 "Jea杨"

需要注意的是:为子类添加属性和方法,需要在对象冒充之后,否则可能出现属性或方法被修改的可能性。

prototype原型继承

版权保护: 本文由 郑州SEO博客 原创,转载请保留链接: http://www.zglblog.cn/html/99.html