1. 程式人生 > >JavaScript(6)--- 原型鏈

JavaScript(6)--- 原型鏈

#
原型鏈
再上一篇有簡單講過原型:[JavaScript(5)--- 面向物件 + 原型](https://www.cnblogs.com/qdhxhz/p/12181259.html) 講原型鏈知識之前,先說幾個重要的結論。 ``` 1、原型鏈就是 物件的__proto__所連線的鏈狀結構 2、prototype 屬性是函式獨有的 3、__proto__ 屬性是物件獨有的,例項原型(Object.prototype)也是物件,所以也會有__proto__屬性 ``` 下面我們一步一步來講解原型鏈 ## 一、prototype屬性 #### 1、建構函式建立物件 我們先使用建構函式建立一個物件: ``` function Person() { } var p = new Person(); p.name = 'xiaoxiao'; console.log(p.name); //xiaoxiao ``` #### 2、 prototype屬性 `概念` 它是 **函式獨有的屬性**,它從一個函式指向另一個物件,代表這個物件是這個函式的原型物件,這個物件也是當前函式所建立的例項的原型物件。 prototype設計之初就是為了實現繼承,讓建構函式建立的所有例項,都能夠共享這個原型屬性和方法。 有了prototype我們不需要為每一個例項建立重複的屬性方法,而是將屬性方法建立在建構函式的原型物件上(prototype)。那些不需要共享的才建立在建構函式中。 `示例` ```javascript function Person(){ } Person.prototype.age=18; //原型屬性 var p1 = new Person(); var p2 = new Person(); console.log(p1.age);//18 console.log(p2.age);//18 ``` `思考` 這個函式的 prototype 屬性到底指向的是什麼呢? 其實,函式的 prototype 屬性指向了一個物件,這個物件正是呼叫該建構函式而建立的例項的原型 。 `思考` 那麼什麼是原型呢? 每一個 JavaScript 物件 (null 除外 ) 在建立的時候就會與之關聯另一個物件,這個物件就是我們所說的原型,每一個物件都會從原型 ” 繼承 ” 屬性。 這裡p1和p2就是例項物件,而Person.prototype就是它們的原型物件。p1和p2可以去繼承原型物件的方法和屬性。 讓我們用一張圖表示建構函式和例項原型之間的關係:

## 二、\__proto\__屬性 `概念` \__proto\__屬性是物件(包括函式,函式也是物件)獨有的。\__proto\__屬性是從一個物件指向另一個物件,該屬性指向的就是該物件的原型物件(也可以理解為父物件)。 `示例` ```javascript function Person(){ } var p = new Person(); console.log(p.__proto__ === Person.prototype);//true ``` `更新下關係圖` \__proto\__通常稱為隱式原型,prototype為顯示原型,那我們可以說一個物件的隱式原型指向了該物件的建構函式的顯示原型。那麼我們在顯示原型上定義的屬性方法, 通過隱式原型傳遞給了建構函式的例項。這樣一來例項就能很容易的訪問到建構函式原型上的方法和屬性了。
## 三、constructor屬性 `概念` constructor是物件才有的屬性,它是從一個物件指向一個函式的。指向的函式就是該物件的建構函式。 注意了 例項原型也是物件,所以也會有constructor屬性,我們來驗證一下 ```javascript function Person(){ } console.log(Person === Person.prototype.constructor);//true console.log(person.constructor); // ƒ Person(){} ``` `再更新下關係圖`
總結 通過上面的演示說明,我們可以得出 ```javascript function Person(){ } var person = new Person(); console.log(person.__proto__ === Person.prototype);//true console.log(Person === Person.prototype.constructor);//true ``` 瞭解了建構函式、例項原型、和例項之間的關係,接下來我們講講例項和原型的關係
## 四、例項與原型 當讀取例項的屬性時,如果找不到,就會查詢與物件關聯的原型中的屬性,如果還查不到,就去找原型的原型,一直找到最頂層為止。 `示例` ```javascript function Person(){ } var person = new Person(); Person.prototype.name='張三'; person.name='李四'; console.log(person.name);//李四 delete person.name; console.log(person.name);//張三 ``` 在這個例子中,我們設定了 person 的 name 屬性,所以我們可以讀取到為 ’李四’ ,當我們刪除了 person 的 name 屬性時,讀取 person.name ,從 person 中找不到 就會從 person 的原型中查詢,name為 ’張三’ 。但是萬一Person.prototype原型中還沒有找到呢?那會到原型的原型去查詢。也就是Object.prototype `示例` ```javascript function Person(){ } var person = new Person(); Person.prototype.name='李四'; person.name='張三'; console.log(person.name);//張三 delete person.name; console.log(person.name);//李四 Object.prototype.name='obj'; delete Person.prototype.name; console.log(person.name);//obj ``` 所以原型物件是通過 Object 建構函式生成的,結合之前所講 , 例項的 \__proto\__ 指向建構函式的 prototype, 所 `再更新下關係圖`

## 五、原型鏈 那 Object.prototypey也是物件,那它也應該會有原型。只不過有是有,只是為`null` , 所以查到 Object.prototype 就可以停止查找了 。 所以最後一張關係圖就是 `總結` 圖中由相互關聯的原型組成的鏈狀結構就是原型鏈,也就是`紅色的這條線`。
### 參考 1、[JavaScript深入之從原型到原型鏈](https://github.com/mqyqingfeng/Blog/issues/2) 非常感謝 2、[JS中的原型與原型鏈](https://www.jianshu.com/p/6ec88183541c) 3、[JavaScript原型&原型鏈](https://www.jianshu.com/p/423f72d502c2) 4、[JS原型鏈簡單圖解](https://www.jianshu.com/p/ca3c10e14bf8) 5、[一道美團外賣面試題](https://blog.csdn.net/lyt_angularjs/article/details/100729591)

``` 別人罵我胖,我會生氣,因為我心裡承認了我胖。別人說我矮,我就會覺得好笑,因為我心裡知道我不可能矮。這就是我們為什麼會對別人的攻擊生氣。 攻我盾者,乃我內心之矛(3