博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[JavaScript 学习笔记] 2. 继承
阅读量:7083 次
发布时间:2019-06-28

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

继承

许多 OO 语言支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。如前所述,由于函数没有签名,在 ECMAScript 中无法实现接口继承。 ECMAScript 只支持实现继承,而且其实现继承主要是依靠原型链来实现。

原型链

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

构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。

jsfunction SuperType() {    this.property = true;}SuperType.prototype.getSuperValue = function() {    return this.property;};function SubType() {    this.subproperty = false;}//继承了 SuperTypeSubType.prototype = new SuperType();SuperType.prototype.getSubValue = function() {    return this.subproperty;}var instance = new SubType();alert(instance.getSuperValue());//true

  1. 别忘记默认的原型

  2. 确定原型和实例的关系

    jsalert(instance instanceof Object); //truealert(instance instanceof SuperType); //truealert(instance instanceof SubType); //true
    jsalert(Object.prototype.isPrototypeOf(instance));//turealert(SuperType.prototype.isPrototypeOf(instance));//turealert(SubType.prototype.isPrototypeOf(instance));//ture
  3. 谨慎地定义方法

    给原型添加方法的代码一定要放在替换原型的语句之后。

    jsfunction SuperType() {this.property = true;}SuperType.protype.getSuperValue = function() {return this.property;}function SubType() {this.subproperty = false;}//继承了 SuperTypeSubType.prototype = new SuperType();//添加新方法SubType.prototype.getSubValue = function() {return this.subproperty;};//重写超类型中的方法SubType.prototype.getSuperValue = function() {return false;};var instance = new SubType();alert(instance.getSuperValue());//false
    jsfunction SuperType() {this.property = true;}SuperType.prototype.getSuperValue = function() {return this.property;}function SubType() {this.subproperty = false;}//继承了 SuperTypeSubType.prototype = new SuperType();//使用字变量添加新方法,会导致上一行代码无效SubType.prototype = {getSubValue : function() {    return this.subproperty;},someOtherMethod = function() {    return false;}};var instance = new SubType();alert(instance.getSuperValue()); //error 原型链被切断(现在的原型包含的是 Object 的实例)。

4.原型链的问题

最主要的问题来自包含引用类型值的原型。前面已经介绍过包含引用类型值的原型属性会被所有实例共享,这也是为什么要在构造函数中而不在原型对象中定义属性的原因。

第二个问题是:在创建子类型的实例时,不能向超类型的构造函数中传递参数。实际上,应该说是没有办法在不影响所有对象实例的情况下,给炒类型的构造函数传递参数。

借用构造函数(伪造对象或经典继承)

即在子类型构造函数的内部调用超类型构造函数。函数只不过是在特定环境中执行代码的对象,所以可通过 apply()call() 方法也可以在(将来)新创建的对象上执行构造函数。

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

传递参数

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

组合继承(伪经典继承)

即将原型链和借用构造函数的方法组合在一起,思路为使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。

js    function SuperType(name) {        this.name = name;        this.colors = ["red","blue","green"];    }    SuperType.prototype.sayName = function() {        alert(this.name);    }    function SubType() {        //继承属性        SuperType.call(this,name);        this.age = age;    }    SubType.prototype = new SuperType();    SubType.prototype.constuctor = SubType();    SubType.prototype.sayAge = function() {        alert(this.age);    }    var instance1 = new("PaddingMe",25);    instance1.colors.push("black");    alert(instance1.colors); //"red,blue,green,black"    instance1.sayName; //"PaddingMe"    instance1.sayAge; //25    var instance2 = new("hw",26);    alert(instance2.colors); //"red,blue,green"    instance2.sayName; //"hw"    instance2.sayAge; //26

原型式继承

js    function object(o) {        function F(){}        F.prototype = o;        return new F();    }    var person = {        name : "PaddingMe";        friends :["hw","wjj","hz"];    }    var antherPerson = object(person);    antherPerson.name = "Hhb";    antherPerson.friends.push("zxp");    var yetAntherPerson = object(person);    yetAntherPerson.name = "Linda";    yetAntherPerson.friends.push("him");    alert(person.friends)//"hw,wjj,hz,zxp,him"

ECMAScirpt 5 中新增 Object.create() 方法规范化了原型式继承。有两个参数,一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。

在传入一个参数情况下,Objetc.create() 和 object() 方法的行为相同。

js    var person = {        name : "PaddingMe";        friends :["hw","wjj","hz"];    }    var antherPerson = Object.create(person);    antherPerson.name = "Hhb";    antherPerson.friends.push("zxp");    var yetAntherPerson = Object.create(person);    yetAntherPerson.name = "Linda";    yetAntherPerson.friends.push("him");    alert(person.friends)//"hw,wjj,hz,zxp,him"

第二个参数与 `Object.defineProperties() 方法的第二个参数格式相同: 每个属性都是通过自己的描述符定义的。

js    var person = {        name : "PaddingMe";        friends :["hw","wjj","hz"];    }    var anthorPerson = Object.create(person, {        name: {            value:"hehe";        }    })    alert(anthorPerson.name);//"hehe"

寄生式继承

即创建一个仅用于封装继承构成的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。

js    function createAnother(original) {        var clone = object(original); //通过调用函数创建一个新对象        clone.sayHi = function() { //以某种方式来增强这个对象            alert("hi");        };        return clone; //返回这个对象    }    var person = {        name : "PaddingMe";        friends :["hw","wjj","hz"];    }    var anthorPerson = createAnother(person);    anthorPerson.sayHi();//"hi"

寄生组合式继承

jsfunction 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.constuctor = SubType;SubType.prototype.sayAge = function(){    alert(this.age);}

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

js    function inheritPrototype(subType,superType){        var prototype = object(superType.prototype); //创建对象        prototype.constructor = subType; //增强对象        subType.prototype = prototype; // 指定对象    }
jsfunction 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;}inheritPrototype(SubType,SuperType);SubType.prototype.sayAge = function(){    alert(this.age);}

转载地址:http://qpmml.baihongyu.com/

你可能感兴趣的文章
SQLServer2005中的CTE递归查询得到一棵树
查看>>
关于营销管理的认知
查看>>
ADO.NET:连接数据字符串
查看>>
全球酷站秀:15个顶尖的 CSS3 网站作品
查看>>
c语言关键字总结
查看>>
DB2中OLAP函数使用示例
查看>>
sql经典语句收集
查看>>
Java代码通过API操作HBase的最佳实践
查看>>
C#调用C++编写的DLL函数, 以及各种类型的参数传递 z
查看>>
[GeoServer]Openlayers简单调用
查看>>
关于LINUX在中断(硬软)中不能睡眠的真正原因
查看>>
两种方法连接MySql数据库
查看>>
20款响应式的 HTML5 网页模板【免费下载】
查看>>
程序员:伤不起的三十岁【转载】
查看>>
修改客户端连接的服务器IP地址(内部使用)
查看>>
android点滴之ContentObserver的使用
查看>>
Android文本输入框(EditText)切换密码的显示与隐藏
查看>>
Metasploit数据库问题汇总
查看>>
64位Linux下编译搭建Nginx1.5与PHP5.5(CentOS6.4)
查看>>
ExtJS获取Grid的行数
查看>>