天天看點

原型鍊原型鍊圖解

原型鍊

這裡隻是通過一些案例補充之前對原型,原型鍊,instanceof的細節。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // // 函數構造器
        // console.log(Function); //ƒ Function() { [native code] }

        // // 對象構造器
        // console.log(Object); //ƒ Object() { [native code] }

        // // 數組構造器
        // console.log(Array); //ƒ Array() { [native code] }

        // // 字元串構造器
        // console.log(String); //ƒ String() { [native code] }

        // // 數字構造器
        // console.log(Number); //ƒ Number() { [native code] }

        // // 布爾構造器
        // console.log(Boolean); //ƒ Boolean() { [native code] }



        // 定義一個函數(構造函數)Father
        function Father() { }
        // 使用構造函數建立對象father
        var father = new Father()

        // 使用字面量形式建立對象
        var car = {}

        // 使用Object構造器建立對象
        var home = new Object()

        // 使用字面量形式建立一個數組arr
        var arr = [1, 2, 3]


        /**
         * prototype原型對象,即原型對象也是對象,是對象就可以通過原型鍊繼承其原型上的屬性和方法,
         * prototype是對象,是以prototype也可通過原型鍊繼承其原型上的屬性和方法
        */

        /**
         * 每個對象都可以通過原型鍊通路(或者說繼承)其原型鍊上的屬性和方法
         * 使用構造函數建立的對象,可以通過原型鍊繼承這個構造函數上的屬性和方法(說白了就是這個構造函數的原型)
         * */
        console.log(father.__proto__ === Father.prototype); //true

        /**
         * 這個構造函數的原型對象,即Father.prototype,也可通過原型鍊繼續繼承它(Father.prototype)原型鍊上的屬性和方法
        */
        console.log(Father.prototype.__proto__);   //true
        console.log(Father.prototype.__proto__ === Object.prototype);   //true
        console.log(Father.prototype.constructor === Father);   //true
        // 通過構造函數建立的對象,可以通過原型鍊通路其原型
        console.log(father.__proto__) //true
        // 通過字面量形式建立的對象,其本身就繼承Object.prototype
        console.log(car.__proto__.constructor === Object);
        console.log(arr.__proto__ === Array.prototype); //true

        // 同理,函數實際也是一個對象,是以,函數也可以通過其原型鍊通路其原型
        console.log(Function.__proto__ === Function.prototype);//true
        console.log(Function.__proto__ === Function.prototype);//true
        console.log(Function);




        console.log(Function.prototype); //ƒ () { [native code] }
        /**
         * 所有函數都有自己的prototype
         */
        console.log(Object.prototype); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
        console.log(Array.prototype); //[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
        console.log(String.prototype); //String {"", constructor: ƒ, anchor: ƒ, big: ƒ, blink: ƒ, …}
        console.log(Number.prototype); //Number {0, constructor: ƒ, toExponential: ƒ, toFixed: ƒ, toPrecision: ƒ, …}
        console.log(Boolean.prototype); //Boolean {false, constructor: ƒ, toString: ƒ, valueOf: ƒ}


        console.log(Array.prototype === Function.prototype); //false
        console.log(String.prototype === Function.prototype); //false
        console.log(Number.prototype === Function.prototype); //false

        console.log(Object.__proto__ === Function.prototype);  //true
        console.log(Array.__proto__ === Function.prototype);   //true
        console.log(Function.__proto__ === Function.prototype);//true
        console.log(String.__proto__ === Function.prototype);  //true
        console.log(Number.__proto__ === Function.prototype);  //true
        console.log(Boolean.__proto__ === Function.prototype); //true
        /**
         * Object.protype是原型鍊的頂端,它在往上就是null
         * 其餘所有對象(Array,String,Number...)會通過原型鍊繼承Object.prototype
         */
        console.log(Object.prototype
            .__proto__
        ); //null
        console.log(Array.prototype
            .__proto__
        ); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
        console.log(String.prototype
            .__proto__
        ); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
        console.log(Number.prototype
            .__proto__
        ); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
        console.log(Boolean.prototype
            .__proto__
        ); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
        console.log(Array.prototype.__proto__ === Object.prototype); //true
        console.log(String.prototype.__proto__ === Object.prototype); //true
        console.log(Number.prototype.__proto__ === Object.prototype); //true
        console.log(Boolean.prototype.__proto__ === Object.prototype); //true
        console.log(Array);         //ƒ Array() { [native code] }
        console.log(Array.prototype); //prototype是原型對象,對象就有__proto__。它還有constructor儲存本身,還有本身的屬性以及方法
        console.log(Array.prototype.constructor === Array); //true
        console.log(Array.__proto__ === Function.prototype); //true
        console.log(Array.prototype.__proto__);     //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
        console.log('--------------');



        /**
         * 所有對象都可以通過new建立,比如數組:new Array();對象:new Object();函數:new Function();字元串:new String()....
         * new後面的叫構造函數,即Array();Object();Function();String()...都是構造函數
         * 構造函數也是函數,那麼就有一個問題,js所有東西都是對象的話,是先有對象還是現有構造函數?(因為對象也是new出來的)
         * 如果是先有函數,再通過函數new産生的對象,那麼函數又是怎麼來的?是以就類似:先有雞還是現有雞蛋的問題。
         * 是以,函數是怎麼來的?這個解釋了就說的通了
         * */

        /**
         * 函數有prototype,對象有__proto__
         * 函數可以通過prototype.constructor通路自己構造它的函數
         * 對象可以通過__proto__繼承上層的prototype
        */
        console.log(Function instanceof Object);                         //true
        // 函數就有prototype
        console.log(Function.prototype instanceof Object);               //true
        console.log(Function.prototype.__proto__ instanceof Object);     //fasle
        // 函數也是一個對象,對象就有__proto__,是以函數有__proto__
        console.log(Function.__proto__ instanceof Object);               //true
        console.log(Function.__proto__ instanceof Object);               //true
        console.log(Function.__proto__.__proto__ instanceof Object);     //false
        console.log(Function.__proto__.__proto__ instanceof Object);     //false

        console.log(Function.constructor === Function);                  //true
        console.log('-----------------------');

        var cat = {}
        function Dog() { }
        var dog = new Dog()

        console.log(cat.__proto__ === Function.prototype);      //false
        console.log(dog.__proto__ === Function.prototype);    //false
        console.log(cat.__proto__ === Object.prototype);         //true
        console.log(dog.__proto__ === Object.prototype);          //false
        console.log(cat.__proto__ === dog.__proto__);             //false
        console.log(dog.__proto__ === Dog.prototype);             //true

    </script>
</body>

</html>           

複制

圖解

這裡引用網上的圖,個人也認為這張圖很具體很全面。

原型鍊原型鍊圖解