Skip to content

Commit 8e0a43b

Browse files
author
Phùng Hùng
authored
Merge pull request #12 from hunghedu/master
F.prototype
2 parents 2dec1fc + 59f79ad commit 8e0a43b

File tree

6 files changed

+81
-81
lines changed

6 files changed

+81
-81
lines changed

1-js/08-prototypes/02-function-prototype/1-changing-prototype/solution.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ Answers:
33

44
1. `true`.
55

6-
The assignment to `Rabbit.prototype` sets up `[[Prototype]]` for new objects, but it does not affect the existing ones.
6+
Thay đổi `Rabbit.prototype` chỉ ảnh hưởng tới `[[Prototype]]` của đối tượng được tạo ra sau này, không ảnh hưởng đến các đối tượng đã tạo từ trước.
77

88
2. `false`.
99

10-
Objects are assigned by reference. The object from `Rabbit.prototype` is not duplicated, it's still a single object is referenced both by `Rabbit.prototype` and by the `[[Prototype]]` of `rabbit`.
10+
Đối tượng được gán theo tham chiếu. Đối tượng từ `Rabbit.prototype` không được nhân bản khi gán cho `[[Prototype]]` cho nên `Rabbit.prototype` `[[Prototype]]` của `rabbit` là hai tham chiếu tới một đối tượng.
1111

12-
So when we change its content through one reference, it is visible through the other one.
12+
Nên khi ta thay đổi đối tượng qua một tham chiếu, sự thay đổi này cũng thấy được từ tham chiếu kia.
1313

1414
3. `true`.
1515

16-
All `delete` operations are applied directly to the object. Here `delete rabbit.eats` tries to remove `eats` property from `rabbit`, but it doesn't have it. So the operation won't have any effect.
16+
Hành động xóa bằng toán tử `delete` không tác động tới nguyên mẫu. Ở đây `delete rabbit.eats` chỉ cố xóa thuộc tính `eats` của `rabbit`, nhưng nó không tồn tại. Nên hành động này không gây ảnh hưởng gì.
1717

1818
4. `undefined`.
1919

20-
The property `eats` is deleted from the prototype, it doesn't exist any more.
20+
Thuộc tính `eats` bị xóa khỏi nguyên mẫu, vậy nên nó không thể tìm thấy nữa.

1-js/08-prototypes/02-function-prototype/1-changing-prototype/task.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ importance: 5
22

33
---
44

5-
# Changing "prototype"
5+
# Thay đổi "prototype"
66

7-
In the code below we create `new Rabbit`, and then try to modify its prototype.
7+
Trong mã dưới đây chúng ta định nghĩa một hàm tạo, tạo ra đối tượng và thay đổi prototype mặc định của hàm tạo.
88

9-
In the start, we have this code:
9+
Ban đầu, chúng ta có mã:
1010

1111
```js run
1212
function Rabbit() {}
@@ -20,7 +20,7 @@ alert( rabbit.eats ); // true
2020
```
2121

2222

23-
1. We added one more string (emphasized), what `alert` shows now?
23+
1. Nếu thêm một lệnh nữa (được tô sáng), thì `alert` sẽ hiển thị gì?
2424

2525
```js
2626
function Rabbit() {}
@@ -37,7 +37,7 @@ alert( rabbit.eats ); // true
3737
alert( rabbit.eats ); // ?
3838
```
3939

40-
2. ...And if the code is like this (replaced one line)?
40+
2. ...Và nếu mã trở thành như sau(thay đổi một dòng) thì `alert` sẽ hiển thị gì?
4141

4242
```js
4343
function Rabbit() {}
@@ -54,7 +54,7 @@ alert( rabbit.eats ); // true
5454
alert( rabbit.eats ); // ?
5555
```
5656

57-
3. Like this (replaced one line)?
57+
3. Câu hỏi tương tự nếu mã như sau(thay đổi một dòng)?
5858

5959
```js
6060
function Rabbit() {}
@@ -71,7 +71,7 @@ alert( rabbit.eats ); // true
7171
alert( rabbit.eats ); // ?
7272
```
7373

74-
4. The last variant:
74+
4. Và phiên bản cuối cùng:
7575

7676
```js
7777
function Rabbit() {}
Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
We can use such approach if we are sure that `"constructor"` property has the correct value.
1+
Chúng ta chỉ có thể làm vậy nếu chắn chắn rằng thuộc tính `"constructor"` chứa giá trị đúng.
22

3-
For instance, if we don't touch the default `"prototype"`, then this code works for sure:
3+
Ví dụ, nếu thuộc tính `"prototype"` mặc định không bị thay đổi, thì đoạn mã chắc chắn làm việc được:
44

55
```js run
66
function User(name) {
77
this.name = name;
88
}
99

10-
let user = new User('John');
11-
let user2 = new user.constructor('Pete');
10+
let user = new User('Việt');
11+
let user2 = new user.constructor('Nam');
1212

13-
alert( user2.name ); // Pete (worked!)
13+
alert( user2.name ); // Nam (làm việc!)
1414
```
1515

16-
It worked, because `User.prototype.constructor == User`.
16+
Nó làm việc đúng bởi vì `User.prototype.constructor == User`.
1717

18-
..But if someone, so to say, overwrites `User.prototype` and forgets to recreate `"constructor"`, then it would fail.
18+
...Nhưng nếu ai đó ghi đè mất `User.prototype` và quên tạo lại `"constructor"`, đoạn mã sẽ không làm việc đúng nữa:
1919

20-
For instance:
20+
Ví dụ:
2121

2222
```js run
2323
function User(name) {
@@ -27,18 +27,18 @@ function User(name) {
2727
User.prototype = {}; // (*)
2828
*/!*
2929

30-
let user = new User('John');
31-
let user2 = new user.constructor('Pete');
30+
let user = new User('Việt');
31+
let user2 = new user.constructor('Nam');
3232

3333
alert( user2.name ); // undefined
3434
```
3535

36-
Why `user2.name` is `undefined`?
36+
Tại sao `user2.name` `undefined`?
3737

38-
Here's how `new user.constructor('Pete')` works:
38+
Đây là cách `new user.constructor('Nam')` làm việc:
3939

40-
1. First, it looks for `constructor` in `user`. Nothing.
41-
2. Then it follows the prototype chain. The prototype of `user` is `User.prototype`, and it also has nothing.
42-
3. The value of `User.prototype` is a plain object `{}`, its prototype is `Object.prototype`. And there is `Object.prototype.constructor == Object`. So it is used.
40+
1. Trước tiên nó tìm `constructor` trong `user`. Không có.
41+
2. Sau đó nó theo chuỗi nguyên mẫu. Nguyên mẫu của `user` `User.prototype`, và cũng không có.
42+
3. Giá trị của `User.prototype` là đối tượng trống `{}`, nên mặc định nó thừa kế từ `Object.prototype`. Và có `Object.prototype.constructor == Object`. Nên `Object` được sử dụng.
4343

44-
At the end, we have `let user2 = new Object('Pete')`. The built-in `Object` constructor ignores arguments, it always creates an empty object -- that's what we have in `user2` after all.
44+
Cuối cùng chúng ta có `let user2 = new Object('Nam')`. `Object` là một hàm tạo có sẵn, nó bỏ qua mọi đối số truyền vào và tạo ra một đối tượng trống -- vậy `user2` là đối tượng trống không có thuộc tính nào.

1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/task.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ importance: 5
22

33
---
44

5-
# Create an object with the same constructor
5+
# Tạo đối tượng có cùng constructor
66

7-
Imagine, we have an arbitrary object `obj`, created by a constructor function -- we don't know which one, but we'd like to create a new object using it.
7+
Tưởng tượng, ta có đối tượng bất kỳ `obj`, tạo ra từ một hàm tạo -- chúng ta không biết về hàm này, nhưng lại muốn tạo đối tượng khác bằng nó.
88

9-
Can we do it like that?
9+
Có thể làm như thế này không?
1010

1111
```js
1212
let obj2 = new obj.constructor();
1313
```
1414

15-
Give an example of a constructor function for `obj` which lets such code work right. And an example that makes it work wrong.
15+
Cho biết khi nào đoạn mã trên làm việc và không làm việc, cho ví dụ minh họa từng trường hợp?
Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
# F.prototype
22

3-
Remember, new objects can be created with a constructor function, like `new F()`.
3+
Nhớ rằng, các đối tượng có thể tạo bằng hàm tạo (constructor), chẳng hạn như `new F()`.
44

5-
If `F.prototype` is an object, then `new` operator uses it to set `[[Prototype]]` for the new object.
5+
Nếu `F.prototype` là một đối tượng, thì toán tử `new` dùng nó để đặt cho `[[Prototype]]` của đối tượng mới được tạo ra.
66

77
```smart
8-
JavaScript had prototypal inheritance from the beginning. It was one of the core features of the language.
8+
Từ thuở ban đầu JavaScript đã có thừa kế nguyên mẫu. Đây là một trong những tính năng cốt lõi của ngôn ngữ này.
99
10-
But in the old times, there was no direct access to it. The only thing that worked reliably was a `"prototype"` property of the constructor function, described in this chapter. So there are many scripts that still use it.
10+
Nhưng ngày xưa, không có cách nào để truy cập trực tiếp đến nó. Cách duy nhất có thể dùng để làm việc với thừa kế là sử dụng thuộc tính `"prototype"` của hàm tạo. Vậy nên ngày nay còn nhiều script vẫn sử dụng nó.
1111
```
1212

13-
Please note that `F.prototype` here means a regular property named `"prototype"` on `F`. It sounds something similar to the term "prototype", but here we really mean a regular property with this name.
13+
Chú ý rằng `F.prototype` chỉ là một thuộc tính thông thường có tên `"prototype"` của `F`. Dù tên nó giống thuật ngữ "prototype", nhưng nó không phải là một thuộc tính đặc biệt.
1414

15-
Here's the example:
15+
Đây là ví dụ:
1616

1717
```js run
1818
let animal = {
@@ -32,90 +32,90 @@ let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal
3232
alert( rabbit.eats ); // true
3333
```
3434

35-
Setting `Rabbit.prototype = animal` literally states the following: "When a `new Rabbit` is created, assign its `[[Prototype]]` to `animal`".
35+
Cài đặt `Rabbit.prototype = animal` có nghĩa là: "Khi một đối tượng tạo bằng`new Rabbit`, đặt thuộc tính `[[Prototype]]` của nó thành `animal`".
3636

37-
That's the resulting picture:
37+
Đây là hình ảnh của kết quả:
3838

3939
![](proto-constructor-animal-rabbit.png)
4040

41-
On the picture, `"prototype"` is a horizontal arrow, meaning a regular property, and `[[Prototype]]` is vertical, meaning the inheritance of `rabbit` from `animal`.
41+
Ở hình trên, `"prototype"` là một mũi tên nằm ngang, mang nghĩa là một thuộc tính thông thường, và `[[Prototype]]` là mũi tên thẳng đứng, mang nghĩa `rabbit` thừa kế từ `animal`.
4242

43-
```smart header="`F.prototype` only used at `new F` time"
44-
`F.prototype` property is only used when `new F` is called, it assigns `[[Prototype]]` of the new object. After that, there's no connection between `F.prototype` and the new object. Think of it as a "one-time gift".
43+
```smart header="`F.prototype` chỉ được dùng khi gọi `new F()`"
44+
Thuộc tính `F.prototype` được gán cho `[[Prototype]]` một lần duy nhất khi gọi `new F()`. Sau đó không còn liên hệ giữa `F.prototype` và đối tượng mới này.
4545

46-
If, after the creation, `F.prototype` property changes (`F.prototype = <another object>`), then new objects created by `new F` will have another object as `[[Prototype]]`, but already existing objects keep the old one.
46+
Chẳng hạn, sau khi tạo đối tượng, `F.prototype` bị thay đổi (`F.prototype = <một đối tượng khác>`), thì `[[Prototype]]` của đối tượng không bị thay đổi theo. Sự thay đổi của `F.prototype` chỉ ảnh hưởng tới các đối tượng được tạo ra sau này bằng `new F()`.
4747
```
4848
49-
## Default F.prototype, constructor property
49+
## F.prototype mặc định, thuộc tính "constructor"
5050
51-
Every function has the `"prototype"` property even if we don't supply it.
51+
Mọi hàm đều có sẵn thuộc tính `"prototype"` ngay cả khi ta không tạo.
5252
53-
The default `"prototype"` is an object with the only property `constructor` that points back to the function itself.
53+
Giá trị mặc định của `"prototype"` là một đối tượng chỉ có một thuộc tính duy nhất `constructor` trỏ ngược lại tới hàm.
5454
55-
Like this:
55+
Ví dụ minh họa:
5656
5757
```js
5858
function Rabbit() {}
5959
60-
/* default prototype
60+
/* prototype mặc định (default "prototype")
6161
Rabbit.prototype = { constructor: Rabbit };
6262
*/
6363
```
6464

6565
![](function-prototype-constructor.png)
6666

67-
We can check it:
67+
Chúng ta có thể kiểm tra điều này:
6868

6969
```js run
7070
function Rabbit() {}
71-
// by default:
71+
// theo mặc định:
7272
// Rabbit.prototype = { constructor: Rabbit }
7373

7474
alert( Rabbit.prototype.constructor == Rabbit ); // true
7575
```
7676

77-
Naturally, if we do nothing, the `constructor` property is available to all rabbits through `[[Prototype]]`:
77+
Một cách tự nhiên, nếu ta không làm gì, thuộc tính `constructor` sẽ có sẵn với mọi đối tượng được tạo từ hàm tạo qua `[[Prototype]]`:
7878

7979
```js run
8080
function Rabbit() {}
81-
// by default:
81+
// theo mặc định:
8282
// Rabbit.prototype = { constructor: Rabbit }
8383

84-
let rabbit = new Rabbit(); // inherits from {constructor: Rabbit}
84+
let rabbit = new Rabbit(); // thừa kế từ {constructor: Rabbit}
8585

86-
alert(rabbit.constructor == Rabbit); // true (from prototype)
86+
alert(rabbit.constructor == Rabbit); // true (lấy từ nguyên mẫu)
8787
```
8888

8989
![](rabbit-prototype-constructor.png)
9090

91-
We can use `constructor` property to create a new object using the same constructor as the existing one.
91+
Chúng ta có thể sử dụng thuộc tính `constructor` để tạo đối tượng mới từ constructor của một đối tượng đã có:
9292

93-
Like here:
93+
Chẳng hạn:
9494

9595
```js run
9696
function Rabbit(name) {
9797
this.name = name;
9898
alert(name);
9999
}
100100

101-
let rabbit = new Rabbit("White Rabbit");
101+
let rabbit = new Rabbit("Thỏ trắng");
102102

103103
*!*
104-
let rabbit2 = new rabbit.constructor("Black Rabbit");
104+
let rabbit2 = new rabbit.constructor("Thỏ đen");
105105
*/!*
106106
```
107107

108-
That's handy when we have an object, don't know which constructor was used for it (e.g. it comes from a 3rd party library), and we need to create another one of the same kind.
108+
Cách này rất tiện nếu chúng ta có một đối tượng, không biết constructor nào đã tạo ra nó (ví dụ đối tượng từ một thư viện ngoài), và muốn tạo một đối tượng khác cùng loại.
109109

110-
But probably the most important thing about `"constructor"` is that...
110+
Nhưng nên cẩn thận vì...
111111

112-
**...JavaScript itself does not ensure the right `"constructor"` value.**
112+
**...JavaScript không thể đảm bảo giá trị `"constructor"` luôn đúng.**
113113

114-
Yes, it exists in the default `"prototype"` for functions, but that's all. What happens with it later -- is totally on us.
114+
Vâng, thuộc tính `constructor` tồn tại trong `"prototype"` mặc định của mọi hàm, nhưng đó là tất cả những gì JavaScript làm. Chuyện gì xảy ra sau đó hoàn toàn do chúng ta quyết định.
115115

116-
In particular, if we replace the default prototype as a whole, then there will be no `"constructor"` in it.
116+
Cụ thể, nếu ta thay thế `prototype` mặc định bằng một đối tượng khác không có `constructor`, đối tượng tạo ra không còn biết constructor tạo ra nó nữa.
117117

118-
For instance:
118+
Ví dụ:
119119

120120
```js run
121121
function Rabbit() {}
@@ -129,18 +129,18 @@ alert(rabbit.constructor === Rabbit); // false
129129
*/!*
130130
```
131131

132-
So, to keep the right `"constructor"` we can choose to add/remove properties to the default `"prototype"` instead of overwriting it as a whole:
132+
Cho nên, để giữ lại `"constructor"`, chúng ta phải thêm/xóa các thuộc tính khỏi `prototype` mặc định thay vì ghi đè toàn bộ.
133133

134134
```js
135135
function Rabbit() {}
136136

137-
// Not overwrite Rabbit.prototype totally
138-
// just add to it
137+
// Không ghi đè toàn bộ Rabbit.prototype
138+
// chỉ bổ sung vào đó
139139
Rabbit.prototype.jumps = true
140-
// the default Rabbit.prototype.constructor is preserved
140+
// Rabbit.prototype.constructor vẫn được giữ
141141
```
142142

143-
Or, alternatively, recreate the `constructor` property manually:
143+
Hoặc tạo lại thuộc tính `constructor`:
144144

145145
```js
146146
Rabbit.prototype = {
@@ -150,26 +150,26 @@ Rabbit.prototype = {
150150
*/!*
151151
};
152152

153-
// now constructor is also correct, because we added it
153+
// giờ constructor vẫn đúng, vì chúng ta đã thêm nó
154154
```
155155

156156

157-
## Summary
157+
## Tóm tắt
158158

159-
In this chapter we briefly described the way of setting a `[[Prototype]]` for objects created via a constructor function. Later we'll see more advanced programming patterns that rely on it.
159+
Trong bài này chúng ta đã mô tả ngắn gọn cách cài đặt `[[Prototype]]` cho các đối tượng tạo ra bằng hàm tạo. Sau này bạn sẽ thấy nhiều mô hình lập trình dựa vào nó.
160160

161-
Everything is quite simple, just few notes to make things clear:
161+
Mọi thứ khá đơn giản, chỉ có vài lưu ý sau:
162162

163-
- The `F.prototype` property is not the same as `[[Prototype]]`. The only thing `F.prototype` does: it sets `[[Prototype]]` of new objects when `new F()` is called.
164-
- The value of `F.prototype` should be either an object or null: other values won't work.
165-
- The `"prototype"` property only has such a special effect when set on a constructor function, and invoked with `new`.
163+
- Thuộc tính `F.prototype` không phải là `[[Prototype]]`. Giá trị của `F.prototype` được gán cho `[[Prototype]]` khi gọi `new F()`, sau đó chúng hoàn toàn độc lập nhau.
164+
- Giá trị của `F.prototype` có thể là đối tượng hoặc null: mọi giá trị kiểu cơ sở đều không hoạt động.
165+
- Thuộc tính `"prototype"` chỉ có tác dụng khi cài đặt nó cho một hàm tạo và gọi hàm này bằng `new`.
166166

167-
On regular objects the `prototype` is nothing special:
167+
Nếu cài đặt `prototype` cho một đối tượng thông thường, nó không còn gì đặc biệt:
168168
```js
169169
let user = {
170170
name: "John",
171-
prototype: "Bla-bla" // no magic at all
171+
prototype: "Bla-bla" // không có gì đặc biệt
172172
};
173173
```
174174
175-
By default all functions have `F.prototype = { constructor: F }`, so we can get the constructor of an object by accessing its `"constructor"` property.
175+
Mặc định tất cả các hàm có `F.prototype = { constructor: F }`, giúp ta có thể lấy được hàm tạo của một đối tượng bằng cách truy cập thuộc tính `constructor` của nó.

1-js/08-prototypes/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# Prototypes, inheritance
1+
# Nguyên mẫu, thừa kế

0 commit comments

Comments
 (0)