做者:蘇墨橘
連接:https://www.zhihu.com/question/34183746/answer/59043879
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
react
正好這段時間在從新看這部分,寫一篇回答來梳理一下吧。web
__proto__(隱式原型)與prototype(顯式原型)express
1. 是什麼NOTE Function objects created using Function.prototype.bind do not have a prototype property or the [[Code]], [[FormalParameters]], and [[Scope]] internal properties. ----- ECMAScript Language Specification
隱式原型指向建立這個對象的函數(constructor)的prototype瀏覽器
2. 做用是什麼ECMAScript does not use classes such as those in C++, Smalltalk, or Java. Instead objects may be created in various ways including via a literal notation or via constructors which create objects and then execute code that initialises all or part of them by assigning initial values to their properties. Each constructor is a function that has a property named 「prototype」 that is used to implement prototype-based inheritance and shared properties.Objects are created by using constructors in new expressions; for example, new Date(2009,11) creates a new Date object. ----ECMAScript Language Specification
Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s 「prototype」 ----ECMAScript Language Specification
道格拉斯在2006年寫了一篇文章,題爲 Prototypal Inheritance In JavaScript。在這篇文章中,他介紹了一種實現繼承的方法,這種方法並無使用嚴格意義上的構造函數。他的想法是藉助原型能夠基於已有的對象建立新對象,同時還不比所以建立自定義類型,爲了達到這個目的,他給出了以下函數:
function object(o){ function F(){} F.prototype = o; return new F() } ----- 《JavaScript高級程序設計》P169
//如下是用於驗證的僞代碼 var f = new F(); //因而有 f.__proto__ === F.prototype //true //又由於 F.prototype === o;//true //因此 f.__proto__ === o;
所以由Object.create(o)建立出來的對象它的隱式原型指向o。好了,對象的建立方式分析完了,如今你應該可以判斷一個對象的__proto__指向誰了。函數
好吧,仍是舉一些一眼看過去比較疑惑的例子來鞏固一下。ui
function Foo(){} var foo = new Foo() Foo.prototype.__proto__ === Object.prototype //true 理由同上
function Bar(){} //這時咱們想讓Foo繼承Bar Foo.prototype = new Bar() Foo.prototype.__proto__ === Bar.prototype //true
//咱們不想讓Foo繼承誰,可是咱們要本身從新定義Foo.prototype
Foo.prototype = { a:10, b:-10 } //這種方式就是用了對象字面量的方式來建立一個對象,根據前文所述 Foo.prototype.__proto__ === Object.prototype
注: 以上兩種狀況都等於徹底重寫了Foo.prototype,因此Foo.prototype.constructor也跟着改變了,因而乎constructor這個屬性和原來的構造函數Foo()也就切斷了聯繫。spa
既然是構造函數那麼它就是Function()的實例,所以也就指向Function.prototype,好比 Object.__proto__ === Function.prototypeprototype
4. instanceof//設 L instanceof R
//經過判斷
L.__proto__.__proto__ ..... === R.prototype ?
//最終返回true or false
Function instanceof Object // true Object instanceof Function // true Function instanceof Function //true Object instanceof Object // true Number instanceof Number //false