1
- ## The Prototype
1
+ ## Prototype
2
+
3
+ JavaScript 不包含原本繼承的模型。然而它使用的是 * prototypal* 原型。
2
4
3
- JavaScript does not feature a classical inheritance model; instead, it uses a
4
- * prototypal * one.
5
+ 然而常常有人提及 JavaScript 的缺點,就是基於原本繼承模型比類繼承更強大。
6
+ 現實傳統的類繼承模型是很簡單。但是在 JavaScript 中實現元繼承則要困難很多。
5
7
6
- While this is often considered to be one of JavaScript's weaknesses, the
7
- prototypal inheritance model is in fact more powerful than the classic model.
8
- It is, for example, fairly trivial to build a classic model on top of a
9
- prototypal model, while the other way around is a far more difficult task.
8
+ 由於 JavaScript 是唯一一個被廣泛使用的基於原型繼承的語言,所以我們必須要花時間來理解這兩者的不同。
10
9
11
- JavaScript is the only widely used language that features prototypal
12
- inheritance, so it can take time to adjust to the differences between the two
13
- models.
10
+ 第一個不同之處在於 JavaScript 使用 * 原型鏈* 的繼承方式。
14
11
15
- The first major difference is that inheritance in JavaScript uses * prototype
16
- chains* .
17
-
18
- > ** Note:** Simply using ` Bar.prototype = Foo.prototype ` will result in both objects
19
- > sharing the ** same** prototype. Therefore, changes to either object's prototype
20
- > will affect the prototype of the other as well, which in most cases is not the
21
- > desired effect.
12
+ > ** 注意: ** 簡單的使用 ` Bar.prototype = Foo.prototype ` 將會導致兩個對象共享 ** 相同** 的原型。
13
+ > 因此,改變任一個原型都會去影響到另外一個,這在大部分的時候不是想得到的結果。
22
14
23
15
function Foo() {
24
16
this.value = 42;
@@ -29,16 +21,16 @@ chains*.
29
21
30
22
function Bar() {}
31
23
32
- // Set Bar's prototype to a new instance of Foo
24
+ // 設置 Bar 的 prototype 屬性為 Foo 的實例對象
33
25
Bar.prototype = new Foo();
34
26
Bar.prototype.foo = 'Hello World';
35
27
36
- // Make sure to list Bar as the actual constructor
28
+ // 修正 Bar.prototype.constructor 為 Bar 本身
37
29
Bar.prototype.constructor = Bar;
38
30
39
- var test = new Bar() // create a new bar instance
31
+ var test = new Bar() // 開啟一個新的實例
40
32
41
- // The resulting prototype chain
33
+ // 原型鏈
42
34
test [instance of Bar]
43
35
Bar.prototype [instance of Foo]
44
36
{ foo: 'Hello World' }
@@ -47,70 +39,48 @@ chains*.
47
39
Object.prototype
48
40
{ toString: ... /* etc. */ }
49
41
50
- In the code above, the object ` test ` will inherit from both ` Bar.prototype ` and
51
- ` Foo.prototype ` ; hence, it will have access to the function ` method ` that was
52
- defined on ` Foo ` . It will also have access to the property ` value ` of the
53
- ** one** ` Foo ` instance that is its prototype. It is important to note that `new
54
- Bar()` does **not** create a new ` Foo` instance, but reuses the one assigned to
55
- its prototype; thus, all ` Bar ` instances will share the ** same** ` value ` property.
42
+ 上面的例子中,物件 ` test ` 會繼承來自 ` Bar.prototype ` 和 ` Foo.prototype ` 。因此它可以進入來自 ` Foo ` 原型的方法 ` method ` 。
43
+ 同時它也可以訪問 ** 那個** 定義在原型上的 ` Foo ` 實例屬性 ` value ` 。
44
+
45
+ 要注意的是 ` new Bar() ` ** 沒有** 創立一個新的 ` Foo ` 實例,它重複利用的原本的 prototype。因此, ` Bar ` 的實例會分享到 ** 相同** 的 ` value ` 屬性。
56
46
57
- > ** Note:** Do ** not** use ` Bar.prototype = Foo ` , since it will not point to
58
- > the prototype of ` Foo ` but rather to the function object ` Foo ` . So the
59
- > prototype chain will go over ` Function.prototype ` and not ` Foo.prototype ` ;
60
- > therefore, ` method ` will not be on the prototype chain.
47
+ > ** 注意:** ** 不要** 使用 ` Bar.prototype = Foo ` ,因為這不會執行 ` Foo ` 的原型,而是指向函式 ` Foo ` 。
48
+ > 因此原型鏈將回碩到 ` Function.prototype ` 而不是 ` Foo.prototype ` ,因此 ` method ` 將不會在 Bar 的原型鏈上。
61
49
62
- ### Property Lookup
50
+ ### 屬性查詢
63
51
64
- When accessing the properties of an object, JavaScript will traverse the
65
- prototype chain ** upwards** until it finds a property with the requested name.
52
+ 當查詢一個物件的屬性時,JavaScript 會 ** 向上** 查詢,直到查到指定名稱的屬性為止。
66
53
67
- If it reaches the top of the chain - namely ` Object.prototype ` - and still
68
- hasn't found the specified property, it will return the value
69
- [ undefined] ( #core.undefined ) instead.
54
+ 如果他查到原型鏈的頂部 - 也就是 ` Object.prototype ` - 但是仍然每有指定的屬定,就會返回 [ undefined] ( #core.undefined ) 。
70
55
71
- ### The Prototype Property
56
+ ### 原型屬性
72
57
73
- While the prototype property is used by the language to build the prototype
74
- chains, it is still possible to assign ** any** given value to it. However,
75
- primitives will simply get ignored when assigned as a prototype.
58
+ 當原型屬性用來建造原型鏈,它還是有可能去把 ** 任意** 類型的值給它
76
59
77
60
function Foo() {}
78
- Foo.prototype = 1; // no effect
61
+ Foo.prototype = 1; // 無效
79
62
80
- Assigning objects, as shown in the example above, will work, and allows for dynamic
81
- creation of prototype chains.
63
+ 分派物件,在上面的例子中,將會動態的創建原型鏈。
82
64
83
- ### Performance
65
+ ### 效能
84
66
85
- The lookup time for properties that are high up on the prototype chain can have
86
- a negative impact on performance, and this may be significant in code where
87
- performance is critical. Additionally, trying to access non-existent properties
88
- will always traverse the full prototype chain.
67
+ 如果看在屬性在原型鏈的上端,對於查詢都會有不利的影響。特別的,試圖獲取一個不存在的屬性將會找遍所有原型鏈。
89
68
90
- Also, when [ iterating] ( #object.forinloop ) over the properties of an object
91
- ** every** property that is on the prototype chain will be enumerated.
69
+ 並且,當使用 [ 迴圈] ( #object.forinloop ) 找尋所有物件的屬性時,原型鏈上的 ** 所有** 屬性都會被訪問。
92
70
93
- ### Extension of Native Prototypes
71
+ ### 擴展 Native Prototype
94
72
95
- One mis-feature that is often used is to extend ` Object.prototype ` or one of the
96
- other built in prototypes.
73
+ 一個經常錯誤使用的特定,那就是擴展 ` Object.prototype ` 或者是其他內置類型的原型物件。
97
74
98
- This technique is called [ monkey patching] [ 1 ] and breaks * encapsulation* . While
99
- used by popular frameworks such as [ Prototype] [ 2 ] , there is still no good
100
- reason for cluttering built-in types with additional * non-standard* functionality.
75
+ 這種技術叫做 [ monkey patching] [ 1 ] 並且會破壞 * 封裝* 。雖然被廣泛的應用到一些 Javascript 的架構,但是我仍然認為內置類型添加是一個 * 非標準* 的函式的好方法
101
76
102
- The ** only** good reason for extending a built-in prototype is to backport
103
- the features of newer JavaScript engines; for example,
104
- [ ` Array.forEach ` ] [ 3 ] .
77
+ 擴展內置類型的 ** 唯一** 理由是為了和新的 JavaScript 保持一致,比如說 [ ` Array.forEach ` ] [ 3 ]
105
78
106
- ### In Conclusion
79
+ ### 總結
107
80
108
- It is ** essential** to understand the prototypal inheritance model before
109
- writing complex code that makes use of it. Also, be aware of the length of the
110
- prototype chains in your code and break them up if necessary to avoid possible
111
- performance problems. Further, the native prototypes should ** never** be
112
- extended unless it is for the sake of compatibility with newer JavaScript
113
- features.
81
+ 在寫複雜的程式碼的時候,要 ** 充分理解** 所有程式繼承的屬性還有原型鏈。
82
+ 還要堤防原型鏈過長帶來的性能問題,並知道如何通過縮短原型鏈來提高性能。
83
+ 絕對 ** 不要使用** native prototype` 除非是為了和新的 JavaScript 引擎作兼容。
114
84
115
85
[ 1 ] : http://en.wikipedia.org/wiki/Monkey_patch
116
86
[ 2 ] : http://prototypejs.org/
0 commit comments