博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript中的继承
阅读量:5226 次
发布时间:2019-06-14

本文共 4761 字,大约阅读时间需要 15 分钟。

JavaScript中的继承

一、原型链

ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法。

其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。

1 function SuperType(){ 2     this.property = true; 3 } 4  5 SuperType.prototype.getSuperValue = function() { 6     return this.property; 7 }; 8  9 function SubType() {10     this.subproperty = false;11 }12 13 //继承了 SuperType14 SubType.prototype = new SuperType();15 16 SubType.prototype.getSubValue = function(){17     return this.subproperty;18 };19 20 var instance = new SubType();21 alert(instance.getSuperValue());        //true22 23 alert(instance instanceof Object);        //true24 alert(instance instanceof SuperType);    //true25 alert(instance instanceof SubType);     //true26 27 alert(Object.prototype.isPrototypeOf(instance));        //true28 alert(SuperType.prototype.isPrototypeOf(instance));        //true29 alert(SubType.prototype.isPrototypeOf(instance));        //true

 

二、借用构造函数

在解决原型中包含引用类型值所带来问题的过程中,开发人员开始使用一种叫做借用构造函数(contructor stealing)的技术(也称伪造对象或者经典继承)。这种技术的基本思想是:在子类型构造函数的内部调用超类型构造函数。

别忘了,函数只不过是在特定环境中执行代码的对象,因此通过使用apply()和call()方法也可以在新创建的对象上执行构造函数。

function SuperType(){    this.colors = ["red", "blue", "green"];}function SubType(){    SuperType.call(this);}var instance1 = new SubType();instance1.colors.push("black");alert(instance1.colors);        //"red, blue, green, black"var isntance2 = new SubType();alert(instance2.colors);        //"red, blue, green"

1.传递参数

相对于原型链而言,借用构造函数有一个很大的优势,即可以在子类型构造函数中向超类型构造函数传递参数。

function SuperType(name){    this.name = name;}function SubType(){    //继承了SuperType,同时还传递了参数    SuperType.call(this, "Nicholas");    //实例属性    this.age = 29;}var instance = new SubType();alert(instance.name);    //"Nicholas"alert(instance.age);    //29

2.借用构造函数的问题

如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的一个问题——方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类而言也是不可见的,结果所有类型都只能使用构造函数模式。因此,借用构造函数的计数很少单独使用。

三、组合继承

组合继承(combination inheritance),有时候也叫做伪经典继承,指的是将原型链和借用构造函数的计数组合到一起,从而发挥二者之长的一种继承模式。

其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数实现对实例属性的继承。

1 function SuperType(name){ 2     this.name = name; 3     this.colors = ["red", "blue", "green"]; 4 } 5  6 SuperType.prototype.sayName = function(){ 7     alert(this.name); 8 }; 9 10 funciton SubType(name, age){11     //继承属性12     SuperType.call(this, name);13 14     this.age = age;15 }16 17 //继承方法18 SubType.prototype = new SuperType();19 20 SubType.prototpye.sayAge = function(){21     alert(this.age);22 };23 24 var instance1 = new SubType("Nicholas", 29);25 instance1.colors.push("black");26 alert(instance1.colors);        //"red, blue, green, black"27 28 instance1.sayName();        //"Nicholas"29 instance1.sayAge();            //2930 31 32 var instance2 = new SubType("Greg", 27);33 alert(instance2.colors);        //"red, blue, green"34 instance2.sayName();            //"Greg"35 instance2.sayAge();                //27

 

四、寄生式继承

寄生式(parasitic)继承是与原型继承紧密相关的一种思路。寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象。

function createAnother(original){    var clone = object(orignial);    //通过调用函数创建一个新对象    clone.sayHi = function(){        //以某种方式来增强这个对象        alert("hi");    };    return clone;        //返回这个对象}

 

object() 函数不是必须的,任何能够返回想对象的函数都适于此模式。

使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率;这一点与构造函数模式类似。

 

五、寄生组合式继承(有效的)

组合继承最大的问题就是无论在什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。

子类型最终会包含超累型对象的全部实力属性,但我们不得不在调用子类型构造函数时重写这些属性。

function SuperType(name){    this.name = name;    this.colors = ["red", "blue", "green"];}SuperType.prototype.sayName = function(){    alert(this.name);};function SubType(name, age){    SuperType.call(this, name);        //第二次调用superType()    this.age = age;}SubType.prototype = new SuperType();    //第一次调用SuperType()SubType.prototype.sayAge = function(){    alert(this.age);};

 

两次调用SuperType()的结果就是 name和age属性有两组,一组在SubType原型中,一组在SubType属性中。通过使用寄生组合式继承,可以解决这个问题。

所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

(问题:这样的话,超类型中除原型意外的方法如何得到继承?)

1 function inheritPrototype(subType, superType){ 2     var prototype = object(superType.prototype);    //创建对象 3     prototype.constructor = subType;                //增强对象 4     subType.prototype = prototype;                    //指定对象 5 } 6  7 ========================================================================= 8  9 使用这种形式改写之前的继承:10 11 function SuperType(name){12     this.name = name;13     this.colors = ["red", "blue", "green"];14 }15 16 SuperType.prototype.sayName = function(){17     alert(this.name);18 };19 20 function SubType(name, age){21     SuperType.call(this, name);22 23     this.age = age;24 }25 26 inheritPrototype(SubType, SuperType);27 28 SubType.prototype.sayAge = function(){29     alert(this.age);30 };

 

 

 

转载于:https://www.cnblogs.com/luwei2/archive/2013/02/19/javascript_extend.html

你可能感兴趣的文章
C# Dynamic通用反序列化Json类型并遍历属性比较
查看>>
128 Longest Consecutive Sequence 一个无序整数数组中找到最长连续序列
查看>>
定制jackson的自定义序列化(null值的处理)
查看>>
auth模块
查看>>
javascript keycode大全
查看>>
前台freemark获取后台的值
查看>>
log4j.properties的作用
查看>>
游戏偶感
查看>>
Leetcode: Unique Binary Search Trees II
查看>>
C++ FFLIB 之FFDB: 使用 Mysql&Sqlite 实现CRUD
查看>>
Spring-hibernate整合
查看>>
c++ map
查看>>
exit和return的区别
查看>>
发布一个JavaScript工具类库jutil,欢迎使用,欢迎补充,欢迎挑错!
查看>>
discuz 常用脚本格式化数据
查看>>
洛谷P2777
查看>>
PHPStorm2017设置字体与设置浏览器访问
查看>>
SQL查询总结 - wanglei
查看>>
安装cocoa pods时出现Operation not permitted - /usr/bin/xcodeproj的问题
查看>>
makefile中使用变量
查看>>