js 原型鏈 prototype __proto__


1、說明

函數(Function)才有prototype屬性,對象(除Object)擁有__proto__。

2、prototype與__proto__區別

 

 示例:

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

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>prototype與__proto__區別</title>
    </head>

    <body>
        <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
        <script type="text/javascript">
            var a = {}; console.log(a.prototype); //undefined
 console.log(a.__proto__); //Object {}

            var b = function() {} console.log(b.prototype); //b {}
 console.log(b.__proto__); //function() {}
        </script>
    </body>

</html>

控制台輸出:

 

(3)__proto__指向

示例:

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

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

    <body>
        <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
        <script type="text/javascript">
            /*1、字面量方式*/
            var a = {}; console.log(a.__proto__); //Object {}
 console.log(a.__proto__ === a.constructor.prototype); //true

            /*2、構造器方式*/
            var A = function() {}; var b = new A(); console.log(b.__proto__); //A {}
 console.log(b.__proto__ === b.constructor.prototype); //true

            /*3、Object.create()方式*/
            var a1 = { a: 1 } var a2 = Object.create(a1); console.log(a2.__proto__); //Object {a: 1}
 console.log(a2.__proto__ === a2.constructor.prototype); //false(此處即為圖1中的例外情況)
        </script>
    </body>

</html>

控制台輸出:

(4)原型鏈

(1)是__proto__指向的一條指針鏈!

(2)查找屬性時,首先先查找自身屬性,找不到的話,在查找原型鏈上的屬性。但是不會查找自身的prototype屬性。

示例代碼:

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

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>屬性查找</title>
    </head>

    <body>
        <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
        <script type="text/javascript"> Function.prototype.age = 20; let b = function() {} b.prototype.age = 10; console.log(b.age)//輸出20
        </script>
    </body>

</html>

 

示例:

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

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

    <body>
        <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
        <script type="text/javascript">
            var A = function() {}; var a = new A(); console.log(a.__proto__); //A {}(即構造器function A 的原型對象)
 console.log(a.__proto__.__proto__); //Object {}(即構造器function Object 的原型對象)
 console.log(a.__proto__.__proto__.__proto__); //null
        </script>
    </body>

</html>

(5)prototype

prototypelength是每一個函數類型自帶的兩個屬性,而其它非函數類型並沒有,這一點之所以比較容易被忽略或誤解,是因為所有類型的構造函數本身也是函數,所以它們自帶了prototype屬性:

示例:

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

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

    <body>
        <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
        <script type="text/javascript"> console.log(Object.prototype); //=> {} 
 console.log(Function.prototype); //=> [Function: Empty] 
 console.log(String.prototype); //=> [String: '']
        </script>
    </body>

</html>

除了prototype之外,Js中的所有對象(undefinednull等特殊情況除外)都有一個內置的[[Prototype]]屬性,指向它“父類”的prototype,這個內置屬性在ECMA標准中並沒有給出明確的獲取方式,但是許多Js的實現(如Node、大部分瀏覽器等)都提供了一個__proto__屬性來指代這一[[Prototype]],我們通過下面的例子來說明實例中的__proto__是如何指向構造函數的prototype的:

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

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

    <body>
        <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
        <script type="text/javascript">
            var Person = function() {}; Person.prototype.type = 'Person'; Person.prototype.maxAge = 100; var p = new Person(); p.name = 'rainy'; Person.prototype.constructor === Person; //=> true 
 p.__proto__ === Person.prototype; //=> true 
 console.log(p.prototype); //=> undefined
 console.log(p.maxAge); //100
 console.log(p.__proto__.maxAge); //100
 console.log(p.name); //rainy
 console.log(p.__proto__.name); //undefined
        </script>
    </body>

</html>

圖示:

Person是一個函數類型的變量,因此自帶了prototype屬性,prototype指向中的Person.prototype對象。Person.prototype.constructor又指向Person本身;通過new關鍵字生成的Person類的實例p1,通過__proto__屬性指向了Person的原型。這里的__proto__只是為了說明實例p1在內部實現的時候與父類之間存在的關聯(指向父類的原型),在實際操作過程中實例可以直接通過.獲取父類原型中的屬性,從而實現了繼承的功能。

(6)原型鏈

示例代碼:

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

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

    <body>
        <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
        <script type="text/javascript">
            var Obj = function() {}; var o = new Obj(); o.__proto__ === Obj.prototype; //=> true 
 o.__proto__.constructor === Obj; //=> true
 Obj.__proto__ === Function.prototype; //=> true 
 Obj.__proto__.constructor === Function; //=> true
 Function.__proto__ === Function.prototype; //=> true 
 Object.__proto__ === Object.prototype; //=> false 
 Object.__proto__ === Function.prototype; //=> true
 Function.__proto__.constructor === Function; //=> true 
 Function.__proto__.__proto__; //=> {} 
 Function.__proto__.__proto__ === o.__proto__.__proto__; //=> true 
 o.__proto__.__proto__.__proto__ === null; //=> true
        </script>
    </body>

</html>

(7)null與undefined

null與undefined 無原型

//報錯
 console.log(Object.getPrototypeOf(undefined)) //報錯
            console.log(Object.getPrototypeOf(null))

 

從上面的例子和圖解可以看出,prototype對象也有__proto__屬性,向上追溯一直到null

(8)原型鏈的遍歷過程(一直到null)

 

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

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>原型鏈的遍歷過程</title>
    </head>

    <body>
        <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
        <script type="text/javascript"> let a = 1 console.log(a.__proto__ === Number.prototype) //true
 console.log(Number.__proto__ === Function.prototype) //true
 console.log(Function.__proto__ === Function.prototype) //true
 console.log(Function.__proto__.__proto__ === Object.prototype) //true
 console.log(Function.__proto__.__proto__.__proto__) </script>
    </body>

</html>

 (9)獲取原型對象

Object.getPrototypeOf(object)

(10)原型上可遍歷的屬性

 __proto__ 隱式原型 prototype顯示原型

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM