You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The `"prototype"`property is widely used by the core of JavaScript itself. All built-in constructor functions use it.
3
+
Thuộc tính `"prototype"`được dùng rất nhiều bởi chính JavaScript. Tất cả các constructor có sẵn đều sử dụng nó.
4
4
5
-
We'll see how it is for plain objects first, and then for more complex ones.
5
+
Trước tiên ta tìm hiểu về hàm tạo ra các đối tượng thuần, sau đó là các đối tượng có sẵn phức tạp hơn.
6
6
7
7
## Object.prototype
8
8
9
-
Let's say we output an empty object:
9
+
Giả sử chúng ta có một đối tượng trống:
10
10
11
11
```js run
12
12
let obj = {};
13
13
alert( obj ); // "[object Object]" ?
14
14
```
15
15
16
-
Where's the code that generates the string `"[object Object]"`? That's a built-in `toString` method, but where is it? The `obj` is empty!
16
+
Giá trị xuất ra là chuỗi `"[object Object]"` là do phương thức `toString`, còn thực tế `obj` là rỗng và không hề có `toString`. Vậy `toString` lấy ở đâu?
17
17
18
-
...But the short notation`obj = {}`is the same as `obj = new Object()`, where `Object`is a built-in object constructor function, with its own`prototype`referencing a huge object with `toString` and other methods.
18
+
...Thực ra cách viết`obj = {}`hoàn toàn giống `obj = new Object()`, ở đó `Object`là constructor có sẵn, có thuộc tính`prototype`tham chiếu tới một đối tượng khổng lồ chứa rất nhiều phương thức trong đó có `toString`.
19
19
20
-
Here's what's going on:
20
+
Đây là hình ảnh mô tả chuyện gì đã xảy ra:
21
21
22
22

23
23
24
-
When `new Object()`is called (or a literal object `{...}` is created), the `[[Prototype]]`of it is set to `Object.prototype` according to the rule that we discussed in the previous chapter:
24
+
Khi tạo đối tượng bằng `new Object()`(hoặc bằng `{...}`), `Object.prototype` được gán cho `[[Prototype]]`của đối tượng, đây là quy tắc ta đã học ở bài trước:
25
25
26
26

27
27
28
-
So then when `obj.toString()`is called the method is taken from`Object.prototype`.
28
+
Cho nên khi gọi `obj.toString()`thì phương thức này được lấy từ`Object.prototype`.
Please note that there is no additional `[[Prototype]]`in the chain above `Object.prototype`:
39
+
Chú ý rằng `Object.prototype` không có nguyên mẫu, thuộc tính `[[Prototype]]`của nó là `null`:
40
40
41
41
```js run
42
42
alert(Object.prototype.__proto__); // null
43
43
```
44
44
45
-
## Other built-in prototypes
45
+
## Các nguyên mẫu có sẵn khác
46
46
47
-
Other built-in objects such as `Array`, `Date`, `Function`and others also keep methods in prototypes.
47
+
Các constructor khác như `Array`, `Date`, `Function`... cũng có thuộc tính `prototype` nơi giữ các phương thức có sẵn.
48
48
49
-
For instance, when we create an array `[1, 2, 3]`, the default `new Array()` constructor is used internally. So the array data is written into the new object, and `Array.prototype`becomes its prototype and provides methods. That's very memory-efficient.
49
+
Ví dụ, khi tạo tạo mảng `[1, 2, 3]`, JavaScript tự động gọi `new Array()`. Mảng là đối tượng được tạo ra từ `Array`, và do vậy `Array.prototype`trở thành nguyên mẫu của mảng và cung cấp cho mảng nhiều phương thức có sẵn.
50
50
51
-
By specification, all of the built-in prototypes have `Object.prototype` on the top. Sometimes people say that "everything inherits from objects".
51
+
Tuy nhiên khác với `Object.prototype` các nguyên mẫu này vẫn có nguyên mẫu. Nguyên mẫu của chúng chính là `Object.prototype`. Do vậy người ta còn nói "mọi thứ đều thừa kế từ `Object.prototype`".
52
52
53
-
Here's the overall picture (for 3 built-ins to fit):
Some methods in prototypes may overlap, for instance, `Array.prototype`has its own`toString`that lists comma-delimited elements:
72
+
Các phương thức trong các nguyên mẫu có thể "đè" lên nhau, ví dụ, `Array.prototype`có phương thức`toString`giúp liệt kê các phần tử của mảng với dấu phảy ngăn cách:
73
73
74
74
```js run
75
75
let arr = [1, 2, 3]
76
-
alert(arr); // 1,2,3 <-- the result of Array.prototype.toString
76
+
alert(arr); // 1,2,3 <-- là kết quả của Array.prototype.toString
77
77
```
78
78
79
-
As we've seen before, `Object.prototype`has `toString` as well, but `Array.prototype`is closer in the chain, so the array variant is used.
79
+
Nhưng `Object.prototype`cũng có `toString`. Vậy `arr` lấy `toString` từ `Array.prototype`hay từ `Object.prototype`? Câu trả lời rất đơn giản: nó lấy từ nguyên mẫu gần nó nhất tức `Array.prototype`.
80
80
81
81
82
82

83
83
84
84
85
-
In-browser tools like Chrome developer console also show inheritance (`console.dir` may need to be used for built-in objects):
85
+
Trong Developer console của trình duyệt bạn cũng có thể thấy được chuỗi thừa kế bằng lệnh `console.dir`:
86
86
87
87

88
88
89
-
Other built-in objects also work the same way. Even functions -- they are objects of a built-in `Function` constructor, and their methods (`call`/`apply`and others) are taken from`Function.prototype`. Functions have their own `toString`too.
89
+
Các đối tượng có sẵn khác cũng làm việc tương tự. Ngay cả các hàm -- là đối tượng tạo ra bởi constructor `Function`, thực ra lấy các phương thức của nó(`call`/`apply`và phương thức khác) từ`Function.prototype`. Các hàm cũng có được phương thức `toString`từ đây.
90
90
91
91
```js run
92
92
functionf() {}
93
93
94
94
alert(f.__proto__==Function.prototype); // true
95
-
alert(f.__proto__.__proto__==Object.prototype); // true, inherit from objects
The most intricate thing happens with strings, numbers and booleans.
100
+
Đối với các giá trị kiểu cơ sở như chuỗi, số và giá trị lôgic câu chuyện có phức tạp hơn đôi chút.
101
101
102
-
As we remember, they are not objects. But if we try to access their properties, then temporary wrapper objects are created using built-in constructors`String`, `Number`, `Boolean`, they provide the methods and disappear.
102
+
Như ta đã biết, chúng không phải là các đối tượng. Nhưng nếu ta cố tình truy cập các thuộc tính hay phương thức của chúng, một đối tượng bao được tạo bằng các constructor`String`, `Number`, `Boolean` sẽ thay thế và cung cấp các thuộc tính và phương thức này. Sau khi sử dụng xong đối tượng bảo bị xóa.
103
103
104
-
These objects are created invisibly to us and most engines optimize them out, but the specification describes it exactly this way. Methods of these objects also reside in prototypes, available as `String.prototype`, `Number.prototype`and`Boolean.prototype`.
104
+
Các thuộc tính và phương thức của đối tượng thực ra cũng được lấy từ các nguyên mẫu sẵn có đó là `String.prototype`, `Number.prototype`và`Boolean.prototype`.
105
105
106
-
```warn header="Values `null` and `undefined`have no object wrappers"
107
-
Special values `null`and`undefined`stand apart. They have no object wrappers, so methods and properties are not available for them. And there are no corresponding prototypes too.
106
+
```warn header="Các giá trị `null` and `undefined`không có đối tượng bao"
107
+
Các giá trị `null`và`undefined`khác với tất cả các giá trị cơ sở khác. Chúng không có đối tượng bao, nên cũng không có các thuộc tính và phương thức. Và do đó cũng không có nguyên mẫu.
## Thay đổi các nguyên mẫu có sẵn [#native-prototype-change]
111
111
112
-
Native prototypes can be modified. For instance, if we add a method to `String.prototype`, it becomes available to all strings:
112
+
Các nguyên mẫu có sẵn có thể thay đổi được. Ví dụ, nếu bạn thêm vào `String.prototype` một phương thức, phương thức này có thể được dùng cho mọi chuỗi:
During the process of development, we may have ideas for new built-in methods we'd like to have, and we may be tempted to add them to native prototypes. But that is generally a bad idea.
122
+
Trong quá trình phát triển, chúng ta có thể có những ý tưởng về các phương thức mới và muốn thêm nó vào các nguyên mẫu có sẵn. Nhưng đây không phải là cách làm tốt.
123
123
124
124
```warn
125
-
Prototypes are global, so it's easy to get a conflict. If two libraries add a method `String.prototype.show`, then one of them will be overwriting the other.
125
+
Các nguyên mẫu được dùng ở mọi nơi, nên rất dễ xảy ra xung đột. Nếu hai thư viện cùng thêm phương thức `String.prototype.show`, một trong số chúng sẽ ghi đè lên thư viện kia.
126
126
127
-
So, generally, modifying a native prototype is considered a bad idea.
127
+
Vì thế, nói chung sửa đổi nguyên mẫu có sẵn là một ý tưởng tồi.
128
128
```
129
129
130
-
**In modern programming, there is only one case where modifying native prototypes is approved. That's polyfilling.**
130
+
**Trong lập trình hiện đại, chỉ có một trường hợp duy nhất có thể thay đổi nguyên mẫu có sẵn.Đó là polyfilling.**
131
131
132
-
Polyfilling is a term for making a substitute for a method that exists in JavaScript specification, but not yet supported by current JavaScript engine.
132
+
Polyfilling là tạo một phương thức thay thế cho một phương thức đã có trong đặc tả nhưng chưa được hỗ trợ bởi JavaScript engine hiện tại.
133
133
134
-
Then we may implement it manually and populate the built-in prototype with it.
134
+
Lúc này ta phải tự viết phương thức sao cho nó hoạt động giống như phương thức trong đặc tả, sau đó thêm nó vào nguyên mẫu như trong đặc tả.
135
135
136
-
For instance:
136
+
Ví dụ:
137
137
138
138
```js run
139
-
if (!String.prototype.repeat) { //if there's no such method
140
-
//add it to the prototype
139
+
if (!String.prototype.repeat) { //nếu không có phương thức
140
+
//thêm nó vào nguyên mẫu này
141
141
142
142
String.prototype.repeat=function(n) {
143
-
//repeat the string n times
143
+
//lặp lại chuỗi n lần
144
144
145
-
//actually, the code should be a little bit more complex than that
146
-
// (the full algorithm is in the specification)
147
-
//but even an imperfect polyfill is often considered good enough
145
+
//thực tế mã phức tạp hơn một chút
146
+
// (toàn bộ thuật toán có trong đặc tả)
147
+
//nhưng một phiên bản polyfill chưa hoàn hảo cũng đủ dùng rồi
In the chapter <info:call-apply-decorators#method-borrowing>we talked about method borrowing.
158
+
Trong bài <info:call-apply-decorators#method-borrowing>chúng ta đã nói về mượn phương thức.
159
159
160
-
That's when we take a method from one object and copy it into another.
160
+
Đó là khi chúng ta lấy phương thức của một đối tượng và dùng cho đối tượng khác.
161
161
162
-
Some methods of native prototypes are often borrowed.
162
+
Một số phương thức của các nguyên mẫu có sẵn cũng có thể mượn được.
163
163
164
-
For instance, if we're making an array-like object, we may want to copy some array methods to it.
164
+
Ví dụ, nếu chúng ta tạo một mảng giả, chúng ta muốn lấy vài phương thức của mảng thật cho nó.
165
165
166
-
E.g.
166
+
Ví dụ:
167
167
168
168
```js run
169
169
let obj = {
170
-
0:"Hello",
171
-
1:"world!",
170
+
0:"Chào",
171
+
1:"thế giới!",
172
172
length:2,
173
173
};
174
174
175
175
*!*
176
176
obj.join=Array.prototype.join;
177
177
*/!*
178
178
179
-
alert( obj.join(',') ); //Hello,world!
179
+
alert( obj.join(',') ); //Chào thế giới!
180
180
```
181
181
182
-
It works, because the internal algorithm of the built-in`join`method only cares about the correct indexes and the `length` property, it doesn't check that the object is indeed the array. And many built-in methods are like that.
182
+
Nó làm việc, bởi vì thuật toán bên trong của`join`hoàn toàn áp dụng được cho mảng giả. Còn nhiều phương thức có sẵn khác cũng có thể mượn được như vậy.
183
183
184
-
Another possibility is to inherit by setting `obj.__proto__`to`Array.prototype`, so all `Array` methods are automatically available in `obj`.
184
+
Có một cách khác đó là cài đặt `obj.__proto__`thành`Array.prototype`, và `obj` mượn được tất cả các phương thức của mảng.
185
185
186
-
But that's impossible if `obj`already inherits from another object. Remember, we only can inherit from one object at a time.
186
+
Điều này không thể thực hiện nếu `obj`đã có một nguyên mẫu khác. Nhớ rằng, một đối tượng tại một thời điểm chỉ có một nguyên mẫu.
187
187
188
-
Borrowing methods is flexible, it allows to mix functionality from different objects if needed.
188
+
Việc mượn phương thức rất mềm dẻo, nó cho phép phối hợp các tính năng từ nhiều đối tượng để áp dụng cho đối tượng hiện tại.
189
189
190
-
## Summary
190
+
## Tóm tắt
191
191
192
-
-All built-in objects follow the same pattern:
193
-
-The methods are stored in the prototype (`Array.prototype`, `Object.prototype`, `Date.prototype` etc).
194
-
-The object itself stores only the data (array items, object properties, the date).
195
-
-Primitives also store methods in prototypes of wrapper objects: `Number.prototype`, `String.prototype`, `Boolean.prototype`. Only`undefined`and`null`do not have wrapper objects.
196
-
-Built-in prototypes can be modified or populated with new methods. But it's not recommended to change them. Probably the only allowable cause is when we add-in a new standard, but not yet supported by the engine JavaScript method.
192
+
-Tất cả các đối tượng có sẵn đều tuân theo mô hình:
193
+
-Các phương thức lưu trong nguyên mẫu (`Array.prototype`, `Object.prototype`, `Date.prototype`...).
194
+
-Đối tượng chỉ chứa dữ liệu (phần tử mảng, thuộc tính, ngày/tháng...).
195
+
-Các giá trị cơ sở giữ phương thức trong nguyên mẫu của đối tượng bao: `Number.prototype`, `String.prototype`, `Boolean.prototype`. Chỉ`undefined`và`null`không có đối tượng bao.
196
+
-Các nguyên mẫu có sẵn có thể thay đổi được hoặc bổ sung thêm phương thức mới. Nhưng không nên sửa chúng. Chỉ nên sửa nếu ta cần thêm các phương thức mới có trong đặc tả nhưng chưa được JavaScript engine hỗ trợ.
0 commit comments