3張圖記牢javaScript原型

javaScript原型和原型鏈的詳細介紹網上已經有很多大神文章介紹過,本篇不打算再講原理。如果朋友您已經理解了原型、原型鏈興許這邊文章能起到一點點作用。
說實在的我在實際工作中很少用到原型鏈,頂多在自建的對象原型上或者預定義對象原型上(比如Array.prototype)添加個方法,但我又一直記不住原型鏈。在學習總結之後,我我決定把種種特例拆開來記憶,就像小學學習乘除法時將0和1特殊記憶。

必須瞭解的概念

1、只有函數纔有prototype屬性
2、所有對象都有_ _ proto _ _屬性,它不是ECMA規範定義的,但絕大部分瀏覽器都實現了
3、JavaScript中萬物皆對象,函數也是對象,所以函數既有prototype又有_ _ proto _ _屬性
4、一個對象的_ _ proto _ _屬性指向它的構造函數的prototype(原型),將這句話帶入圖中就更好理解和記憶

不同類型的對象原型鏈圖

1、Object對象
let a = { name:"小明",age:20 }//通過字面量創建的對象
let b = new Object()//通過構造函數創建的對象

這類Object對象的原型鏈最簡單,如下圖:


2、Function對象
let c = function() {}//函數表達式
let d = new Function()//通過構造函數創建的函數

這類的Function對象的原型鏈:


3、其他對象
let e = new Array()//預定義類型的對象

class Cat {
 constructor(){}
}
let f = new Cat()//通過其他function new出的對象

最後兩個圖中,從typeof Function.prototype === function可以看出Function.prototype也是一個函數對象,所以它也有prototype屬性,而它的prototype屬性是undefined,也是特殊的一個地方
下面是具體的實驗:

    class Cat {
      constructor() {
      }
    }
    let mycat = new Cat();
    console.log("1-1:", mycat instanceof Cat);
    console.log("1-2:", Cat.prototype);
    console.log("1-3:", Cat.__proto__);
    console.log("1-4:", mycat.__proto__);
    console.log("1-5:", typeof Cat.prototype);
    console.log("1-6:", Cat.__proto__ === Function.prototype);
    console.log("1-7:", Object.prototype === Cat.prototype.__proto__);
    console.log("1-8:", Cat.prototype.constructor === Cat);    
    console.log("1-9:", mycat.__proto__ === Cat.prototype);

    let a = {};
    console.log("2-1:", a.__proto__);
    console.log("2-2:", a.prototype);
    console.log("2-3:", a.__proto__ === Cat.prototype.__proto__);
    console.log("2-4:", a.__proto__.__proto__);

    let b = new Object();
    console.log("3-1:", b.__proto__);
    console.log("3-2:", b.__proto__ === Object.prototype);
    console.log("3-3:", b.__proto__ === Cat.prototype.__proto__);
    console.log("3-4:", b.__proto__.__proto__);

    let c = function(arg1, arg2) {
      let cc = "hello";
    };
    console.log("4-1:", c.__proto__);
    console.log("4-2:", c.prototype);
    console.log("4-3:", c.__proto__ === Function.prototype);
    console.log("4-4:", c.__proto__.__proto__ == Object.prototype);
    console.log("4-5:", c.__proto__.__proto__.__proto__);

    let d = new Function();
    console.log("5-1:", d.__proto__);
    console.log("5-2:", d.prototype);
    console.log("5-3:", d.__proto__ === Function.prototype);
    console.log("5-4:", d.__proto__.__proto__ == Object.prototype);
    console.log("5-5:", d.__proto__.__proto__.__proto__);
    console.log("5-6:", Function.__proto__ === Function.prototype);
    console.log("5-7:", Function.prototype.__proto__ === Object.prototype);

    let e = new Array()
    console.log("6-1:", e.__proto__);
    console.log("6-2:", e.__proto__ === Array.prototype);
    console.log("6-3:", e.__proto__ === Cat.prototype.__proto__);
    console.log("6-4:", e.__proto__.__proto__);
    
    console.log("7-1:", typeof Function.prototype);
    console.log("7-2:", typeof Object.prototype);
    console.log("7-3:", Function.prototype.prototype);


在chrome裏Function.prototype通過console.log()打印是出來的是f(){[native code]}其實就是Function.prototype.toString()的結果,是 native 的代碼實現的 built-in 函數,而不是 JavaScript 代碼。但這並不是語言標準規定的,只是恰好 Chrome 都這麼做了,不過這裏不需要關心~。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章