__proto__ 和 prototype的關係
先上答案:
對象上都有__proto__屬性(函數也是對象)
一般情況下對象的__proto__屬性指向該對象的構造函數的原型對象。
函數上纔有prototype屬性,該屬性指向該函數的原型對象。
OK,下面來詳細解釋一下
什麼是__proto__
這個其實是一個 internal slot (翻譯成內置槽?),叫做 [[ prototype ]] ,也稱爲隱式原型。在js裏所有的普通對象都會有。它的值要麼是 null(原型鏈的最終), 要麼還是一個對象。
之前並沒有一個標準的方法來訪問這個值,但是大多數瀏覽器都支持通過用.__proto__來得到它的值。所以 [[ prototype ]] 就被叫成了 __proto__ 。直到ES5中增加了標準的方法 :Object.getPrototypeOf()
All ordinary objects have an internal slot called [[Prototype]]. The value of this internal slot is either null or an object and is used for implementing inheritance.
什麼是prototype
所有用 function 語句、函數字面量或者 Function 構造函數定義的函數都會同時自動創建一個 prototype 屬性,指向該函數的原型對象。
另外,通過Function.prototype.bind()創建的函數沒有 prototype 屬性。
NOTE 1 Function objects created usingFunction.prototype.bind
are exotic objects. They also do not have aprototype
property.
這裏 Function 的 prototype 有點不同,實際上它是內部對象%FunctionPrototype%,它本身是一個內置函數對象。
它有一些特殊的規則,比如 Function.prototype.length === 0 等
The Function prototype object is the intrinsic object %FunctionPrototype%. The Function prototype object is itself a built-in function object. When invoked, it accepts any arguments and returns undefined. It does not have a [[Construct]] internal method so it is not a constructor.NOTEThe Function prototype object is specified to be a function object to ensure compatibility with ECMAScript code that was created prior to the ECMAScript 2015 specification.
The value of the [[Prototype]] internal slot of the Function prototype object is the intrinsic object %ObjectPrototype% (19.1.3). The initial value of the [[Extensible]] internal slot of the Function prototype object is true.
The Function prototype object does not have a
prototype
property.The value of the
length
property of the Function prototype object is 0.The value of the
name
property of the Function prototype object is the empty String.
Object 的 prototype 也有一點不一樣,它其實是內部對象%ObjectPrototype%,它本身是一個普通對象。
做爲對象它的 __proto__ 也就是 [[prototype]] 值爲 null 。
Object.prototype上掛載着valueOf,toString等方法。
The Object prototype object is the intrinsic object %ObjectPrototype%. The Object prototype object is an ordinary object.The value of the [[Prototype]] internal slot of the Object prototype object is null and the initial value of the [[Extensible]] internal slot is true.
兩者的關係
先上一張神圖 :
每個被構造函數創建出來的對象都有一個隱式引用,指向其構造函數的prototype屬性的值。此外,一個原型可能對它的原型有一個非空的隱式引用,以此類推,就叫做原型鏈。
Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s "prototype"
property. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain. When a reference is made to a property in an object, that reference is to the property of that name in the first object in the prototype chain that contains a property of that name. In other words, first the object mentioned directly is examined for such a property; if that object contains the named property, that is the property to which the reference refers; if that object does not contain the named property, the prototype for that object is examined next; and so on.
看圖說話
構造函數 Foo 的原型屬性 prototype 指向了原型對象 Foo.prototype 。f1, f2 是Foo的實例,通過指向原型對象的__proto__ 就可以繼承原型對象上公有的方法。同時,Foo.prototype 上constructor 屬性指回 構造函數 Foo。
構造函數Foo本身也是對象,所以也有 __proto__ ,指向了Foo的構造函數的原型對象,也就是Function.prototype。
原型對象也是對象,所以也有 __proto__ ,指向Object.prototype。最終Object.prototype.__proto__指向 null。
(完) :)