一步一步捋清prototype
前言
- 剛剛開始學習JavaScript時,被動地認爲這是一門「面向對象的語言」,但各類原理和c++,java等典型的面嚮對象語言明顯不一樣,「原型鏈」,es6中的「class」,都彰顯着js中面向對象的不同凡響。
- 究竟什麼是原型prototype呢?如何在JavaScript中實現「類」呢?
一張圖
圖片分析
這是我總結的一張圖片,簡單的描繪了原型和構造函數、實例間的複雜關係。java
- 全局對象window屬性Object(此處僅用來舉例,其他屬性暫且不提),指向Object()這個函數對象
- Object中存着prototype,它指向了原型(原型中包含了對象的全部方法和屬性)
- 當咱們聲明一個實例
let obj = new Object()
, 你能夠發現它天生就帶着__proto__屬性。而__prototype居然和Object.prototype
指向了同一個對象。咱們知道,它就是原型。
一些思考
1.Object.prototype
(即對象類的原型)的原型是什麼呢?c++
- 咱們不妨打印出來試一試:
應該和你想的同樣,對象類的原型就是原型鏈的盡頭了,它只是一個普通的對象,並無原型。
2.Object.prototype
中的constructor是什麼?有什麼用?es6
- 你應該還記得咱們剛剛像這樣
let obj = new Object();
建立了一個對象實例obj,那麼再來看看這個,你應該就一目瞭然了
沒錯,constructor存在的意義就是爲了讓實例化地對象找到它的構造函數。(對實例化的數組,constructor指向Array;對實例化地函數,constructor指向Function)
3.但你不能人爲constructor指向的必定是構造出當前對象的函數。數組
- 例如,你能說出Object.prototype.constructor指向誰嗎?
你看,這個結果是否是很讓人頭大??
Object.prototype
指向了原型,而原型的constructor的又指回了Object。實際上這種試驗是無心義的,由於咱們要知道,constructor是提供給實例,用來定位它的構造函數的屬性,而不是給原型自己使用的。
- 而這種Object.prototype.constructor ===Object的現象,其實源於人爲設計。爲了讓實例的對象都繼承原型中的constructor,沒法避免出現這種現象。
4.咱們嘗試更深刻一些?嘗試剖析一下數組對象的相關結構。bash
- 問題1:Array.prototype.proto === ?
- 直接來看結果吧
- 爲何會有這種結果呢?其實咱們只須要理解清Array.prototype的本質就行了,其實Array.prototype只是一個Object()構造出的對象實例而已,一個對象實例的原型固然是Object.prototype啊!換句話說Array.prototype和obj在本質上是同樣的!
- 問題2:let arr=[1,2,3];
屬於對象的方法hasOwnProperty是如何在數組實例上生效的呢?
- arr在自身尋找hasOwnProperty方法,發現沒有。
- arr又到他爸爸arr.__proto__即Array.prototype中尋找hasOwnProperty方法,仍然找不到 =
- arr再到他爺爺arr.proto.__proto__即Object.prototype中尋找,找到了這個方法,因而arr調用了這個方法。
prototype vs class
代碼對比
// prototype方法
function Person( name, age) {
this.name = name,
this.age = age
}
Person.prototype.sayHi = function() {
console.log('你好,我叫'+this.name);
}
//class方法
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
sayHi() {
console.log('你好,我叫'+this.name);
}
}
複製代碼
體會
- class只是prototype方法的語法糖而已,本質上沒有區別
- 理解prototype => 熟練使用prototype => 無壓力使用class