zoukankan      html  css  js  c++  java
  • JavaScript原型链详解

      prototype属性是JavaScript为每个Function()实例创建的一个对象。具体地说,它将通过new关键字创建的对象实例 链接回创建它们的构造函数。因此,实例才可以共享或继承通用方法和属性。

      重要的是,共享发生在属性查找时。

      注意:JavaScript会为每个函数创建原型对象,不管你是否打算将这个函数作为构造函数使用。

      即使不直接调用Function()构造函数(如var add = new Function('x', 'y', 'return x+y');),而是使用字面量表示法(如var add = function(x, y) {return x+y};),所有函数也都是由Function()构造函数创建的。

    var myFunction = function() {}
    
    console.log(myFunction.prototype) // object {}, protoype来自于Function构造函数
    
    console.log(typeof myFunction.prototype) // 'object'
    

      默认的prototype属性是Object()对象

      原型只是一个被称为“原型”的空对象属性,它是由javascript在后台创建,并通过调用Function()构造函数来使用。

      虽然原型只是一个对象,但它是特殊的,因为原型链将每个实例都链接至其构造函数的prototype属性。使用new关键字由构造函数创建对象时(或为原始值穿件对象包装器时),都会在创建的对象实例和创建对象的构造函数的prototype属性之间添加一个隐藏的链接。该链接在实例中被称为__proto__。

    Array.prototype.foo = 'foo'
    var myArray = new Array()
    
    console.log(myArray.__proto__.foo) // foo,访问Array.prototype
    

      由于访问__proto__并不是ECMA标准的一部分,有一个更通用的方法,用于跟踪从对象到它集成的原型对象的链接,就是使用构造函数

    console.log(myArray.constructor.prototype.foo) // foo,访问Array.prototype
    // 或使用链
    console.log(myArray.foo) // foo,追踪到Array.prototype

      myArray.__proto__和myArray.constructor.prototype引用Array.prototype

      原型链的最后是Object.prototype,与作用域链类似,原型链查找时将使用它找到的第一个值

    Object.prototype.foo = 'object-foo'
    Array.prototype.foo = 'array-foo'
    var myArray = []
    
    console.log(myArray.foo)
    
    myArray.foo = 'bar'
    console.log(myArray.foo)
    

      用新对象替换prototype属性会删除默认构造函数属性

    var Foo = function() {}
    
    Foo.prototype.constructor === Foo // true
    
    var fooInstance = new Foo()
    
    fooInstance.constructor === Foo // true
    
    Foo.prototype = {} // Foo.prototype.constructor 被修改为默认的Object
    
    var fooInstance = new Foo()
    
    fooInstance.constructor === Foo // false
    fooInstance.constructor === Object // true
    

      如果要替换javascript设置的默认prototype属性,应该重新连接引用该构造函数的构造函数属性。

    var Foo = function() {}
    Foo.prototype = {constructor: Foo}
    var fooInstance = new Foo()
    
    fooInstance.constructor === Foo // true
    

      继承原型属性的实例总是能获得最新值

    var Foo = function() {}
    Foo.prototype.x = 1
    var fooInstance = new Foo()
    console.log(fooInstance.x) // 1
    Foo.prototype.x = 2
    console.log(fooInstance.x) // 2
    

      

    var Foo = function() {}
    Foo.prototype = {x: 1} // 不管是使用默认原型对象还是使用自己的对象覆盖它,查找链的工作方式都是相同的
    var fooInstance = new Foo()
    console.log(fooInstance.x) // 1
    Foo.prototype.x = 2
    console.log(fooInstance.x) // 2
    

      使用新对象替换prototype属性不会更新以前的实例

    var Foo = function() {}
    Foo.prototype.x = 1
    var fooInstance = new Foo()
    console.log(fooInstance.x) // 1
    Foo.prototype = {x: 2}
    console.log(fooInstance.x) // 1
    
    var newFooInstance = new Foo()
    console.log(newFooInstance.x) // 2
    
    //一旦开始创建实例,就不应该用一个新对象替换对象的原型。这样做将导致实例有一个指向不同原型链的链接
    

      用户自定义构造函数像原生构造函数一样原型继承

    var Person = function() {}
    Person.prototype.legs = 2
    Person.prototype.arms = 2
    Person.prototype.countLimbs = function() {return this.legs + this.arms}
    
    var chuck = new Person()
    console.log(chuck.countLimbs()) // 4
    

      为了更好的演示如何使用原型,可以创建一个构造函数,如果这些属性不是作为参数提供的话,则该构造函数的实例继承legs和arms属性

    var Person = function(legs, arms) {
      this.legs = legs;
      this.arms = arms;
    }
    Person.prototype.legs = 2
    Person.prototype.arms = 2
    Person.prototype.countLimbs = function() {return this.legs + this.arms}
    
    var chuck = new Person(0, 0)
    console.log(chuck.countLimbs()) // 0
    

      

  • 相关阅读:
    yum 下载安装包以及依赖包
    《将博客搬至CSDN》
    Lucene
    Solr
    LVS原理详解(3种工作模式及8种调度算法)
    正向代理与反向代理
    网关,网卡
    NAT地址转换
    Nginx学习总结
    网络_OSI模型_数据包传输
  • 原文地址:https://www.cnblogs.com/daqianduan/p/4384272.html
Copyright © 2011-2022 走看看