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

    主要是参考了《JavaScript高级程序设计(第三版)》这本书,根据自己的理解,做了下面的记录

    继承是面向对象(OO)语言里面的概念,有俩种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。由于函数没有签名,在javascript里面无法实现接口继承,只支持实现继承。

    原型链继承

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

      

       所有函数的默认原型都是Object的实例

       那如果让原型对象等于另一个类型的实例会怎么样呢?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型也包含着指向另一个构造函数的指针。

       具体代码: 

     1    function SuperType() {
     2       this.proterty = true
     3     }
     4     SuperType.prototype.getSuperValue = function () {
     5       return this.proterty
     6     }
     7     function SubType() {
     8       this.subproperty = false
     9     }
    10     //继承了SuperType
    11     SubType.prototype = new SuperType()
    12     SuperType.prototype.getSubValue = function () {
    13       return this.subproperty
    14     }
    15     var instance = new SubType()
    16     instance.getSuperValue()  //true

    判断原型和实例的关系

    使用instance或者isPrototypeOf

    1     alert(instance instanceof SubType)  //  true
    2     alert(SubType.prototype.isPrototypeOf(instance))  // true

    缺点:

     (一)、只要某个实例、构造函数、原型对象修改了属性或方法,会对原型链上的其他对象实例造成影响

     (二)、在创建了类型的实例时,没有办法在不影响谁有对象实例的情况下,给超类型的构造函数传递参数

    借用构造函数

        

     1     function SuberType() {
     2       this.colors = ["red","blur"]
     3     }
     4     function SubType() {
     5       //继承了SuberType 
     6       //使用了call改变了this的作用域,用apply也可以
     7       SuberType.call(this)
     8     }
     9     var instance = new  SubType()
    10     instance.colors.push("black")
    11     alert(instance.colors) //red,blur,black
    13 var instalce2 = new SuberType() 14 alert(instalce2.colors) // red,blur

    优点:可以在子类型构造函数中向超类型构造函数传递参数

     1      function SuberType(name) {
     2         this.name = name
     3       }
     4       function SubType() {
     5         //继承了SuberType,还传递了参数
     6         SuberType.call(this,"zhao")
     7         this.age = "27"
     8       }
     9       var instance = new SubType()
    10       alert(instance.name) //zhao
    11       alert(instance.age) //27

    缺点:

    方法都在构造函数中定义,函数无法复用。而且在超类型的原型中定义的方法,子类型是不可见的

    组合继承

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

         

     1    function SuberType(name) {
     2       this.name = name
     3       this.colors = ["red","blue"]
     4     }
     5     SuberType.prototype.sayName = function () {
     6       alert(this.name)
     7     }
     8     function SubType(name,age) {
     9       //继承属性
    10       SuberType.call(this, name)  // 第一次调用SuberType()
    11       this.age = age
    12     }
    13     //继承方法
    14     SubType.prototype = new SuberType()  //第二次调用SuberType()
    15     SubType.prototype.sayAge = function () {
    16       alert(this.age)
    17     }
    18     var instance1 = new SubType("zhao", 27)
    19     instance1.colors.push("black")
    20     alert(instance1.colors) // red,blue,black
    21     instance1.sayName() // zhao
    22     instance1.sayAge()  //27
    23 
    24     var instance2 = new SubType("w", 28)
    25     alert(instance2.colors) // red,blue
    26     instance2.sayName() // w
    27     instance2.sayAge() // 28

    优点:实例有各自的属性,和相同的方法

    缺点:会俩次调用超类型的构造函数

    原型式继承

        借助原型可以基于已有的对象创建新对象,不必因此自定义类型

        

    1    function object(o) {
    2       function F() {}
    3         F.prototype = o
    4         return new F()6     }

    上面这个函数的本质是:object()对传入的对象执行了一次浅复制

     1  var person = {
     2       name: 'zhao',
     3       friends: ['zhao1','zhao2','zhao3']
     4     }
     5     var anotherPerson = object(person)
     6     anotherPerson.name = 'ss'
     7     anotherPerson.friends.push('Bob')
     8 
     9     var yetAnotherPerson = object(person)
    10     yetAnotherPerson.name = 'rr'
    11     yetAnotherPerson.friends.push('Bar')
    12     alert(person.friends) //zhao1,zhao2,zhao3,Bob,Bar

    ECMAScript5通过新增Object.create()方法规范了原型式继承,这个方法接收俩个参数,一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象

    在传入一个参数的情况下,Object.create()和object()一样

     1     var person = {
     2       name: 'zhao',
     3       friends: ['zhao1','zhao2','zhao3']
     4     }
     5     var anotherPerson = Object.create(person)
     6     anotherPerson.name = 'ss'
     7     anotherPerson.friends.push('Bob')
     8 
     9     var yetAnotherPerson = Object.create(person)
    10     yetAnotherPerson.name = 'rr'
    11     yetAnotherPerson.friends.push('Bar')
    12     alert(person.friends) //zhao1,zhao2,zhao3,Bob,Bar

    Object.create()的第二个参数会覆盖原型对象上的同名属性

     1     var person = {
     2       name: 'zhao',
     3       friends: ['zhao1','zhao2','zhao3']
     4     }
     5     var anotherPerson = Object.create(person)
     6     anotherPerson.name = 'ss'
     7     anotherPerson.friends.push('Bob')
     8 
     9     var yetAnotherPerson = Object.create(person)
    10     yetAnotherPerson.name = 'rr'
    11     yetAnotherPerson.friends.push('Bar')
    12     alert(person.friends) //zhao1,zhao2,zhao3,Bob,Bar

    寄生式继承

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

       

     1 <script>
     2      function object(o) {
     3        function F() {}
     4        F.prototype = o
     5        return new F()
     6      }
     7 
     8      function createAnother(original) {
     9        var clone = object(original)  // 通过调用函数创建一个新对象
    10        clone.sayHi = function () {  // 以某种方式来增强这个对象
    11          alert("hi")
    12        }
    13        return clone  //返回这个对象
    14      }
    15      var person = {
    16        name: "zhaobao",
    17        friends: ["zhaobao1","zhaobao2","zhaobao3"]
    18      }
    19      var anotherPerson = createAnother(person)
    20      anotherPerson.sayHi() // hi
    21    </script>

    寄生组合式继承

        这个主要是为了解决组合继承的缺点

       思路:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

                  不必为了指定子类型的原型而调用超类型的构造函数,我们需要的只是超类型原型的一个副本。

                   本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

           基本模式

               

    1   function inheritPrototype(subType, superType) {
    2        var prototype = object(superType) //创建对象
    3        prototype.constructor = subType  // 增强对象
    4        subType.prototype = prototype  //指定对象
    5      }

    例子

      

     1 function inheritPrototype(subType, superType) {
     2        var prototype = object(superType) //创建对象
     3        prototype.constructor = subType  // 增强对象
     4        subType.prototype = prototype  //指定对象
     5      }
     6      function SuperType(name) {
     7        this.name = name
     8        this.colors = ["red","blue"]
     9      }
    10      SuperType.prototype.sayName = function () {
    11        alert(this.name)
    12      }
    13      function SubType(name,age) {
    14        SuperType.call(this,name)
    15        this.age = age
    16      }
    17      inheritPrototype(SubType,SuperType)
    18      SuperType.prototype.sayAge = function () {
    19        alert(this.age)
    20      }

     这个例子的高效率提现在它只调用了一次SuperType构造函数,并且因此避免了在SubType.prototype上面创建不必要的、多余的属性。与此同时,原型链还能保持不变,因此,还能正常使用instanceof和isPrototypeOf()

    这是最理想的继承方式

  • 相关阅读:
    mock of python
    Linux系统有7个运行级别(runlevel)
    linux下gsoap的初次使用
    python的sitecustomize.py妙用
    blkid命令 获取文件系统类型、UUID
    linux的一些核心配置文件
    Linux网卡配置与绑定
    CentOS 5.4 制作 Python 2.6 RPM 包的方法
    学会理解并编辑fstab
    HTTP协议通信过程汇总
  • 原文地址:https://www.cnblogs.com/zhaobao1830/p/7153491.html
Copyright © 2011-2022 走看看