javascript原型
by Pranav Jindal
通過普拉納夫·金達爾
JavaScript的原型:古怪,但這是它的工作原理 (Prototype in JavaScript: it’s quirky, but here’s how it works)
The following four lines are enough to confuse most JavaScript developers:
以下四行足以使大多數JavaScript開發人員感到困惑:
Object instanceof Function//true
Object instanceof Object//true
Function instanceof Object//true
Function instanceof Function//true
Prototype in JavaScript is one of the most mind-boggling concepts, but you can’t avoid it. No matter how much you ignore it, you will encounter the prototype puzzle during your JavaScript life.
JavaScript中的原型是最令人難以置信的概念之一,但您無法避免。 無論您多么忽略它,您在JavaScript的生活中都會遇到原型難題。
So let’s face it head-on.
因此,讓我們面對現實吧。
Starting with basics, there are following data types in JavaScript:
從基礎開始,JavaScript中包含以下數據類型:
- undefined 未定義
- null 空值
- number 數
- string 串
- boolean 布爾值
- object 目的
First five are primitive data types. These store a value of their type such as a boolean, and can be true or false.
前五個是原始數據類型。 它們存儲其類型的值(例如boolean),并且可以為true或false 。
The last “object” is a reference type which we can describe as a collection of key-value pairs (but it is much more).
最后一個“對象”是一種引用類型,我們可以將其描述為鍵-值對的集合(但要多得多)。
In JavaScript, new objects are made using Object constructor function (or object literal {}
) which provides generic methods like toString()
and valueOf()
.
在JavaScript中,使用對象構造 函數 (或對象常量{}
) 創建了新對象,該函數提供了諸如toString()
和valueOf()
類的通用方法。
Functions in JavaScript are special objects which can be “called”. We make them and by using the Function constructor function (or function literal). The fact that these constructors are objects as well as function has always confused me, much in the same way the chicken-egg riddle confuses everyone.
JavaScript中的函數是可以“ 調用”的特殊對象。 我們通過使用Function構造函數 (或函數文字)來制作它們。 這些構造函數既是對象又是函數,這一事實始終使我感到困惑,就像雞肉蛋之謎使所有人困惑一樣。
Before starting with Prototypes, I want to clarify that there are two prototypes in JavaScript:
在開始原型之前,我想澄清一下JavaScript中有兩個原型:
prototype: This is a special object which is assigned as property of any function you make in JavaScript. Let me be clear here, it is already present for any function you make, but not mandatory for internal functions provided by JavaScript (and function returned by
bind
). Thisprototype
is the same object that is pointed to by the[[Prototype]]
(see below) of the a newly created object from that function (usingnew
keyword).prototype :這是一個特殊的對象,它被分配為您在JavaScript中所做的任何函數的屬性。 在這里讓我清楚一點,它對您創建的任何函數都已經存在,但對于JavaScript提供的內部函數(以及
bind
返回的函數)不是必需的。 該prototype
與對象所指向的對象相同。 該函數中新創建的對象的[[Prototype]]
(請參見下文)(使用new
關鍵字)。[[Prototype]]: This is a somehow-hidden property on every object which is accessed by the running context if some property which is being read on the object is not available. This property simply is a reference to the
prototype
of the function from which the object was made. It can be accessed in script using special getter-setter (topic for another day) called__proto__
. There are other new ways to access this prototype, but for sake of brevity, I will be referring to[[Prototype]]
using__proto__
.[[Prototype]]:這是每個對象的某種隱藏屬性,如果正在對象上讀取的某些屬性不可用,則運行上下文可以訪問該對象。 該屬性只是對
prototype
的引用 制成對象的功能。 可以使用名為__proto__
特殊getter-setter (另一天的主題)以腳本的方式進行訪問。 還有其他訪問此原型的新方法,但是為了簡潔起見,我將參考[[Prototype]]
使用__proto__
。
var obj = {}var obj1 = new Object()
The above two statements are equal statements when used to make a new object, but a lot happens when we execute any of these statements.
上面的兩個語句在用于創建新對象時是相等的語句,但是當我們執行其中的任何一條語句時,都會發生很多事情。
When I make a new object, it is empty. Actually it is not empty because it is an instance of the Object
constructor, and it inherently gets a reference of prototype
of Object,
which is pointed to by the __proto__
of the newly created object.
當我制作一個新對象時,它是空的。 實際上,它不是空的,因為它是 Object
構造函數,并且固有地獲取prototype
的引用 的Object,
__proto__
指向的 新創建的對象。
If we look at the prototype
of Object
constructor function, it looks the same as the __proto__
of obj.
In fact, they are two pointers referring to the same object.
如果我們看一下Object
構造函數的prototype
,它看起來與obj.
的__proto__
相同obj.
實際上,它們是指向同一對象的兩個指針。
obj.__proto__ === Object.prototype//true
Every prototype
of a function has an inherent property called constructor
which is a pointer to the function itself. In the case of Object
function, the prototype
has constructor
which points back to Object
.
每個prototype
功能的 具有一個稱為constructor
的固有屬性,該屬性是指向函數本身的指針。 對于Object
函數, prototype
具有constructor
指向Object
。
Object.prototype.constructor === Object//true
In the picture above, the left side is the expanded view of the Object
constructor. You must be wondering what are all these other functions over it. Well, functions are objects, so they can have properties over them as other objects can.
在上圖中,左側是Object
構造函數的展開圖。 您一定想知道它上面的所有其他功能是什么。 函數是對象 ,因此它們可以像其他對象一樣具有屬性。
If you look closely, the Object
(on left) itself has a __proto__
which means that Object
must have been made from some other constructor which has a prototype.
As Object
is a function object, it must have been made using Function
constructor.
如果仔細觀察, Object
(左側)本身具有__proto__
這意味著該Object
必須由其他具有prototype.
構造函數制成prototype.
作為Object
是一個功能對象,它必須是使用Function
制成的 構造函數。
__proto__
of Object
looks same as prototype
of Function
.When I check the equality of both, they turn out to be the same objects.
__proto__
Object
看起來和Function
prototype
一樣。 當我檢查兩者的相等性時,它們原來是相同的對象。
Object.__proto__ === Function.prototype//true
If you look closely, you will see the Function
itself has a __proto__
which means that Function
constructor function must have been made from some constructor function which has a prototype
. As Function
itself is a function, it must have been made using Function
constructor, that is, itself. I know that sounds weird but when you check it, it turns out to be true.
如果仔細觀察,您會看到Function
本身有一個__proto__
這意味著Function
構造函數 必須由具有prototype
某些構造函數制成。 作為Function
本身是一個函數 ,它必須是使用Function
制成的 構造函數,即本身。 我知道這聽起來很怪異,但是當您檢查它時,事實證明它是真實的。
The __proto__
of Function
and prototype
of Function
are in fact two pointers referring to the same object.
__proto__
Function
和prototype
Function
是 實際上,兩個指針指向同一個對象。
Function.prototype === Function.__proto__\\true
As mentioned earlier, the constructor
of any prototype
should point to the function that owns that prototype.
The constructor
of prototype
of Function
points back to Function
itself.
如前所述,任何prototype
的constructor
應該指向擁有該prototype.
的函數prototype.
constructor
prototype
Function
指向Function
本身。
Function.prototype.constructor === Function\\true
Again, the prototype
of Function
has a __proto__
.Well, that’s no surprise… prototype
is an object, it can have one. But notice also that it points to the prototype
of Object
.
再次, prototype
Function
有一個__proto__
嗯,這并不奇怪…… prototype
是一個對象,它可以有一個。 但還要注意,它指向prototype
Object
。
Function.prototype.__proto__ == Object.prototype\\true
So we can have a master map here:
所以我們可以在這里有一個主地圖:
instanceof Operatora instanceof b
The instanceof
operator looks for the object b
pointed to by any of the constructor
(s) of chained __proto__
on a
. Read that again! If it finds any such reference it returns true
else false
.
的 instanceof
運算符尋找對象b
指向 任何的constructor
(多個) 的鏈式__proto__
上a
。 再讀一遍! 如果找到任何此類引用,則返回true
否則為false
。
Now we come back to our first four instanceof
statements. I have written corresponding statements that make instanceof
return true
for the following:
現在我們回到我們的前四個instanceof
陳述。 我寫了相應的語句,使instanceof
返回true
對于以下內容:
Object instanceof FunctionObject.__proto__.constructor === Function
Object instanceof ObjectObject.__proto__.__proto__.constructor === Object
Function instanceof FunctionFunction.__proto__.constructor === Function
Function instanceof ObjectFunction.__proto__.__proto__.constructor === Object
Phew!! Even spaghetti is less tangled, but I hope things are clearer now.
ew! 即使是意大利面也不會那么糾結,但我希望現在情況會更加清楚。
Here I have something that I did not pointed out earlier that prototype
of Object
doesn’t have a __proto__
.
這里有一些我之前沒有指出的Object
prototype
沒有__proto__
。
Actually it has a __proto__
but that is equal to null
. The chain had to end somewhere and it ends here.
實際上它有一個__proto__
但這等于null
。 鏈條必須在某處結束,并在此處結束。
Object.prototype.__proto__\\null
Our Object
, Function
, Object.prototype
and Function.prototype
also have properties which are functions, such as Object.assign
, Object.prototype.hasOwnProperty
and Function.prototype.call
. These are internal functions which do not have prototype
and are also instances of Function
and have a __proto__
which is a pointer to Function.prototype
.
我們的Object
, Function
, Object.prototype
和 Function.prototype
也具有作為函數的屬性,例如Object.assign
, Object.prototype.hasOwnProperty
和 Function.prototype.call
。 這些是內部函數,沒有prototype
,也是Function
實例,具有__proto__
這是指向Function.prototype
的指針。
Object.create.__proto__ === Function.prototype\\true
You can explore other constructor functions like Array
and Date
, or take their objects and look for the prototype
and __proto__
. I’m sure you will be able to make out how everything is connected.
您可以探索其他構造函數,例如Array
和 Date
,或者拿走他們的東西并尋找prototype
和 __proto__
。 我相信您將能夠弄清一切之間的聯系。
額外查詢: (Extra queries:)
There’s one more question that bugged me for a while: Why is it that prototype
of Object
is object and prototype
of Function
is function object?
有一個更多的竊聽我的問題了一會兒:為什么是它prototype
的Object
是對象和prototype
的Function
是函數對象 ?
Here is a good explanation for it if you were thinking the same.
這里 如果您也這么想的話,這是一個很好的解釋。
Another question that might be a mystery for you until now is: How do primitive data types get functions like toString()
, substr()
and toFixed()
? This is well explained here.
到目前為止,您可能還不清楚的另一個問題是:原始數據類型如何獲取諸如toString()
, substr()
和toFixed()
類的函數? 這很好地解釋了這里 。
Using prototype
, we can make inheritance work with our custom objects in JavaScript. But that is a topic for another day.
使用prototype
,我們可以使繼承與JavaScript中的自定義對象一起使用。 但這是另一天的話題。
Thanks for reading!
謝謝閱讀!
翻譯自: https://www.freecodecamp.org/news/prototype-in-js-busted-5547ec68872/
javascript原型