資料--JavaScript原型鏈

JavaScript原型鏈

目錄javascript

  1. 建立對象有幾種方法
  2. 原型、構造函數、實例、原型鏈
  3. instanceof的原理
  4. new運算符

 建立對象的方法

  在瞭解原型鏈以前,首先先了解一下建立對象的幾種方式,介紹如下三種。html

代碼:java

複製代碼
<script type="text/javascript">
    // 第一種方式:字面量
    var o1 = {name: 'o1'}
    var o2 = new Object({name: 'o2'})
      // 第二種方式:構造函數
    var M = function (name) { this.name = name; }
    var o3 = new M('o3')
      // 第三種方式:Object.create
    var p = {name: 'p'}
    var o4 = Object.create(p)

  console.log(o1)    
  console.log(o2)
  console.log(o3)
  console.log(o4)
</script>
複製代碼

 

打印結果:函數

對象是建立出來了,但你可能對結果很詫異,爲何不一樣呢?別急,慢慢來。post

 原型及原型鏈

先來一張容易讓人懵逼的圖this

什麼是原型對象?實例?構造函數?spa

概念就很少說了,看代碼吧prototype

var M = function (name) { this.name = name; }
var o3 = new M('o3')
  •  實例就是對象,在本例中o3就是實例,M就是構造函數。
  • 實例經過new一個構造函數生成的。
  • 從上圖中能夠知道,實例的__protpo__指向的是原型對象。
  • 實例的構造函數的prototype也是指向的原型對象。 
  • 原型對象的construor指向的是構造函數。

 

再來經過下面這個圖來理解一下 3d

 

那什麼是原型鏈呢?code

  簡單理解就是原型組成的鏈,對象的__proto__它的是原型,而原型也是一個對象,也有__proto__屬性,原型的__proto__又是原型的原型,就這樣能夠一直經過__proto__想上找,這就是原型鏈,當向上找找到Object的原型的時候,這條原型鏈就算到頭了。

原型對象和實例之間有什麼做用呢?

經過一個構造函數建立出來的多個實例,若是都要添加一個方法,給每一個實例去添加並非一個明智的選擇。這時就該用上原型了。

在實例的原型上添加一個方法,這個原型的全部實例便都有了這個方法。

接着上面的例子繼續演示:

複製代碼
var M = function (name) { this.name = name; }
var o3 = new M('o3')
var o5 = new M()
o3.__proto__.say=furnction(){
   console.log('hello world')
}

o3.say()
o5.say()
複製代碼

 

打印結果

按照JS引擎的分析方式,在訪問一個實例的屬性的時候,如今實例自己中找,若是沒找到就去它的原型中找,還沒找到就再往上找,直到找到。這就是原型鏈。

補充:

只有函數有prototype,對象是沒有的。

可是函數也是有__proto__的,由於函數也是對象。函數的__proto__指向的是Function.prototype。

也就是說普通函數是Function這個構造函數的一個實例。

 

instanceof原理

instanceof是判斷實例對象的__proto__和生成該實例的構造函數的prototype是否是引用的同一個地址。

是返回true,否返回false。

注意:實例的instanceof在比較的時候,與原型鏈上想上找的的構造函數相比都是true。

 繼續上面的代碼

那怎麼判斷實例是由哪一個構造函數生成的呢?這時候就要用到constructor了。

實例的原型的構造函數, obj.__proto__.constructor

 

new運算符

new運算符的原理

  • 一個新對象被建立。它繼承自foo.prototype。
  • 構造函數返回一個對象。在執行的時候,相應的傳參會被傳入,同時上下文(this)會被指定爲這個新的實例。
  • new foo等同於new foo(), 只能用在不傳遞任何參數的狀況
  • 若是構造函數反悔了一個對象,那個這個對象會取代整個new出來的結果。若是構造函數沒有返回對象,那個new出來的結果爲步驟1建立的對象。

 下面根據new的工做原理經過代碼手動實現一下new運算符

複製代碼
var new2 = function (func) {
    var o = Object.create(func.prototype);    //建立對象
    var k = func.call(o);             //改變this指向,把結果付給k
    if (typeof k === 'object') {         //判斷k的類型是否是對象
        return k;                  //是,返回k
    } else {
        return o;                  //不是返回返回構造函數的執行結果
    }
}    
複製代碼

 

 驗證

 

通過上圖一系列折騰,不難看出,咱們手動編寫的new2和new運算符的做用是同樣的。

經過這個例子,你是否是已經熟知了new的工做原理了呢

相關文章
相關標籤/搜索