zoukankan      html  css  js  c++  java
  • js继承

    问题:为什么要继承?js中继承的方式有哪些?

     1为什么要继承?原则是什么?

    1 reduce the amount of duplicate code
    2 make your objects as loosely coupled as possible

    总的原则:减少重复代码,减少耦合

    2继承的方式

    2.1类式继承,一步一步来改进

    2.11继承最简单的方式。

    function A1(){}
    A1.prototype
    ={}
    function A2(){}
    A2.prototype
    =new A1;

    2.12 继承常用的方式—组合继承

    如果上面的代码中, function A1(this.colors=["red"])
    这时: var a1=new A2; a1.colors.push("yellow")
        var a2=new A2; a2.colors;
    这时,a2.colors的值是什么?
    这时a2.colors也一起改变了。所以改进为以下方式
    function A1(){}
    A1.prototype
    ={}
    function A2(){A1.call(this)}
    A2.prototype
    =new A1;

    2.13  继承的完美方式—寄生式组合继承(高级2上的名字有点长,我把它叫做完美继承)

    如果这样,A1.call(this)就覆盖了new A1中的值。这样是没有问题了。但是A1执行了2次!new了一次,call又执行了一次!
    所以,考虑让A2.prototype的值只继承A1.prototype。A1中的内容通过A1.call来继承。这样就完美了。
    那该怎么做呢?

    考虑1:如果直接尝试直接将 A2.prototype=A1.prototype .这样直接引用.这样会产生问题。如果更改A2的prototype,那么A1的prototype也会改变

    考虑2:如果浅拷贝:for(var i in A1.prototype) A2.prototype[i]=A1.prototype[i].这样的话1:prototype中方法不能太多。2:A1的prototype如果改动的话,A2就没法继承了。

    考虑3:如果深拷贝:A2.prototype=深拷贝A1.prototype.这样还是上面的问题。

    继承总结:A1的prototype中的值是可改变的,并且A1的改动会影响到A2;A2的prototype是可改变的,A2的改动不能影响到A1.

    A2.prototype=new A1 其实就需要 A2.prototype.__proto__=A1.prototype 也就是
    var temp={};temp.__proto__=A1.prototype;A2.prototype=temp 因为__proto__是隐藏属性,所以改成下面
    var temp=function(){}; temp.prototype=A1.prototype; A2.prototype=new temp

    最终代码如下

    function extend(A2,A1){
    var F=function(){};
    F.prototype
    =A1.prototype;
    A2.prototype
    =new F;
    A2.prototype.constructor
    =A2;//重建
    A2.super=A1.prototype;//新建
    }

    function
     A1(a){this.a=a}
    A1.prototype.say
    =function(){}
    function A2(a){A1.call(this,a)}
    extend(A1,A2)
    A2.prototype.say2
    =function(){}

     这里指定一个super属性,这样可以减少耦合,因为在不知道A1.prototype的情况下,可以通过A2.super来访问A1.prototype

    类式继承总结:A中的值是任意的值,不管是数组引用,或者是对象包含对象。A.prototype中的必须是方法,不能是引用,也不能是对象包含对象。

     2.2 原型式继承
    类似继承要求我们必须创建构造函数,而原型继承则可以直接使用对象字面量形式.

    var clone=function(a){function F(){};F.prototype=a;return new F;}
    var g1={name:"",colors:["yellow"]}
    var g2=clone(g1)
    g2.name
    ="free";g2.colors.push("red")
    var g3=clone(g1)
    g3.name
    ="riyue";g3.colors.push("green")
    //这样,name被覆盖了,但是colors是引用。colors需要被深拷贝覆盖。
    //
    以上就等于
    function f1(){};f1.prototype={name:"",colors:["yellow"],constructor:Object}
    //下面是一个改进的原型式继承,在有数组引用,或者对象中包含对象的情况下。使用函数返回值。
    var b={name:function(){return ["free"]},age:22}
    var b2=clone(b)
    var b3=clone(b)
    b2.name
    =b2.name()
    b2.name.push(
    "free2")
    console.info(b2.name,b3.name())

     2.3 掺元类
    实现把一个函数用到多个类中。
    加入我现在有一个函数M。现在要让A1和A2类有这个函数

    var M=function(){}
    M.prototype.serialize
    =function(){var o=[];for(var i in this) o.push(i+":"+this[i]);return o.join(",");}  //一个函数。用于返回对象的每个属性
    function augment(r,g){for(var i in g.prototype){if(!r.prototype[i])r.prototype[i]=g.prototype[i]}}    //实现函数
    function A2(){this.a=1}
    augment(A2,M)  
    //实现方式
    var a2=new A2
    document.write(a2.serialize())  
    //这个类的对象可以使用和这个函数了

    参考资料:《js高级程序设计2》,《js设计模式》

  • 相关阅读:
    mysql重置id
    mysql数据类型
    手把手教你新建一个Vue项目
    用markdown开始优雅的写作
    源码阅读心得
    断点调试-程序员的必修课
    代码还是短点好!
    GoJS v1.8.27 去水印方法
    VS code不用集成终端如何修改并推送分支?
    LeetCode日拱一卒
  • 原文地址:https://www.cnblogs.com/lunalord/p/2100930.html
Copyright © 2011-2022 走看看