Skip to content

Commit b38e33d

Browse files
author
Phùng Hùng
authored
Merge pull request #8 from hunghedu/master
Property flags and descriptors
2 parents a6a17ab + 07fe072 commit b38e33d

File tree

1 file changed

+86
-86
lines changed
  • 1-js/07-object-properties/01-property-descriptors

1 file changed

+86
-86
lines changed
Lines changed: 86 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,83 @@
11

2-
# Property flags and descriptors
2+
# Các cờ và descriptor
33

4-
As we know, objects can store properties.
4+
Như ta đã biết, đối tượng có thể lưu các thuộc tính.
55

6-
Till now, a property was a simple "key-value" pair to us. But an object property is actually a more flexible and powerful thing.
6+
Đến lúc này, chúng ta chỉ biết chúng là một cặp "key-value" (phương thức là thuộc tính có `value` là hàm). Nhưng thuộc tính và phương thức của đối tượng thực sự linh hoạt và mạnh mẽ hơn nhiều.
77

8-
In this chapter we'll study additional configuration options, and in the next we'll see how to invisibly turn them into getter/setter functions.
8+
Trong bài này, chúng ta sẽ học về các cấu hình bổ sung cho thuộc tính, và trong bài tiếp theo là cách để biến chúng thành các hàm getter và setter.
99

10-
## Property flags
10+
## Các "cờ" của thuộc tính
1111

12-
Object properties, besides a **`value`**, have three special attributes (so-called "flags"):
12+
Các thuộc tính, ngoài giá trị `value` còn có ba đặc tính đặc biệt khác gọi là ba "cờ" hay "flag", đó là:
1313

14-
- **`writable`** -- if `true`, can be changed, otherwise it's read-only.
15-
- **`enumerable`** -- if `true`, then listed in loops, otherwise not listed.
16-
- **`configurable`** -- if `true`, the property can be deleted and these attributes can be modified, otherwise not.
14+
- **`writable`** -- nếu là `true`, thì giá trị chuộc tính có thể thay đổi, nếu không nó chỉ có thể đọc (read-only).
15+
- **`enumerable`** -- nếu là `true`, thì thuộc tính được liệt kê trong các vòng lặp.
16+
- **`configurable`** -- nếu là `true`, thì có thể xóa thuộc tính và sửa lại cờ của nó.
1717

18-
We didn't see them yet, because generally they do not show up. When we create a property "the usual way", all of them are `true`. But we also can change them anytime.
18+
Chúng ta chưa từng thấy các cờ này, bởi thông thường chúng không hiện ra. Khi chúng ta tạo một thuộc tính theo cách thông thường, tất cả các cờ đều là `true`. Nhưng chúng ta cũng có thể thay đổi chúng bất cứ lúc nào.
1919

20-
First, let's see how to get those flags.
20+
Trước tiên, cùng xem cách để lấy các cờ trên:
2121

22-
The method [Object.getOwnPropertyDescriptor](mdn:js/Object/getOwnPropertyDescriptor) allows to query the *full* information about a property.
22+
Phương thức [Object.getOwnPropertyDescriptor](mdn:js/Object/getOwnPropertyDescriptor) cho phép lấy *toàn bộ* thông tin của một thuộc tính (gồm các cờ và giá trị).
2323

24-
The syntax is:
24+
Cú pháp là:
2525
```js
2626
let descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);
2727
```
2828

2929
`obj`
30-
: The object to get information from.
30+
: Là đối tượng chứa thuộc tính.
3131

3232
`propertyName`
33-
: The name of the property.
33+
: Là tên thuộc tính.
3434

35-
The returned value is a so-called "property descriptor" object: it contains the value and all the flags.
35+
Giá trị trả về là một đối tượng chứa giá trị và tất cả các cờ của thuộc tính. Đối tượng này còn được gọi là "property desciptor" (bộ mô tả thuộc tính) hay ngắn gọn là **descriptor**.
3636

37-
For instance:
37+
Ví dụ:
3838

3939
```js run
4040
let user = {
41-
name: "John"
41+
name: "Hùng"
4242
};
4343

4444
let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
4545

4646
alert( JSON.stringify(descriptor, null, 2 ) );
4747
/* property descriptor:
4848
{
49-
"value": "John",
49+
"value": "Hùng",
5050
"writable": true,
5151
"enumerable": true,
5252
"configurable": true
5353
}
5454
*/
5555
```
5656

57-
To change the flags, we can use [Object.defineProperty](mdn:js/Object/defineProperty).
57+
Để thay đổi descriptor, chúng ta sử dụng [Object.defineProperty](mdn:js/Object/defineProperty).
5858

59-
The syntax is:
59+
Cú pháp là:
6060

6161
```js
6262
Object.defineProperty(obj, propertyName, descriptor)
6363
```
6464

6565
`obj`, `propertyName`
66-
: The object and property to work on.
66+
: Đối tượng và tên thuộc tính cần thay đổi.
6767

6868
`descriptor`
69-
: Property descriptor to apply.
69+
: Đối tượng "descriptor" sử dụng.
7070

71-
If the property exists, `defineProperty` updates its flags. Otherwise, it creates the property with the given value and flags; in that case, if a flag is not supplied, it is assumed `false`.
71+
Nếu thuộc tính đã tồn tại, `defineProperty` cập nhật lại descriptor của nó. Nếu không, thuộc tính được tạo với giá trị và cờ được cung cấp bởi `descriptor`. Khi thuộc tính được tạo theo cách này, các cờ không được cung cấp sẽ nhận giá trị mặc định là `false`.
7272

73-
For instance, here a property `name` is created with all falsy flags:
73+
Ví dụ, thuộc tính `name` được tạo với tất cả các cờ là `false`:
7474

7575
```js run
7676
let user = {};
7777

7878
*!*
7979
Object.defineProperty(user, "name", {
80-
value: "John"
80+
value: "Hùng"
8181
});
8282
*/!*
8383

@@ -86,7 +86,7 @@ let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
8686
alert( JSON.stringify(descriptor, null, 2 ) );
8787
/*
8888
{
89-
"value": "John",
89+
"value": "Hùng",
9090
*!*
9191
"writable": false,
9292
"enumerable": false,
@@ -96,17 +96,17 @@ alert( JSON.stringify(descriptor, null, 2 ) );
9696
*/
9797
```
9898

99-
Compare it with "normally created" `user.name` above: now all flags are falsy. If that's not what we want then we'd better set them to `true` in `descriptor`.
99+
So sánh nó với cách tạo `user.name` thông thường ở ví dụ trước: tất cả các cờ đều `false`. Nếu muốn các thuộc tính được tạo như bình thường chúng ta nên cài đặt tất cả cờ là `true` trong `descriptor`.
100100

101-
Now let's see effects of the flags by example.
101+
Bây giờ, cùng xem các cờ có tác dụng gì bởi các ví dụ.
102102

103-
## Read-only
103+
## Thuộc tính "chỉ đọc"
104104

105-
Let's make `user.name` read-only by changing `writable` flag:
105+
Để tạo thuộc tính chỉ đọc ta đặt cờ `writable` `false`:
106106

107107
```js run
108108
let user = {
109-
name: "John"
109+
name: "Hùng"
110110
};
111111

112112
Object.defineProperty(user, "name", {
@@ -116,58 +116,58 @@ Object.defineProperty(user, "name", {
116116
});
117117

118118
*!*
119-
user.name = "Pete"; // Error: Cannot assign to read only property 'name'...
119+
user.name = "Mạnh"; // Lỗi: Không thể gán cho thuộc tính chỉ đọc 'name'...
120120
*/!*
121121
```
122122

123-
Now no one can change the name of our user, unless they apply their own `defineProperty` to override ours.
123+
Lúc này không thể thay đổi giá trị của thuộc tính nữa trừ khi đặt lại `writable` thành `true` bằng `defineProperty` một lần nữa.
124124

125-
```smart header="Errors appear only in use strict"
126-
In the non-strict mode, no errors occur when writing to read-only properties and such. But the operation still won't succeed. Flag-violating actions are just silently ignored in non-strict.
125+
```smart header="Lỗi chỉ xuất hiện trong chế độ nghiêm ngặt"
126+
Nếu không sử dụng chế độ nghiệm ngặt (`"use strict"`) sẽ không có lỗi xảy ra khi thay đổi giá trị của thuộc tính chỉ đọc. Nhưng hành động này vẫn không thể thực hiện thành công.
127127
```
128128

129-
Here's the same operation, but for the case when a property doesn't exist:
129+
Cũng như trên, nhưng đây là trường hợp thuộc tính không tồn tại:
130130

131131
```js run
132132
let user = { };
133133

134134
Object.defineProperty(user, "name", {
135135
*!*
136-
value: "Pete",
137-
// for new properties need to explicitly list what's true
136+
value: "Hùng",
137+
// đặt các cờ khác là true
138138
enumerable: true,
139139
configurable: true
140140
*/!*
141141
});
142142

143-
alert(user.name); // Pete
144-
user.name = "Alice"; // Error
143+
alert(user.name); // Hùng
144+
user.name = "Ngọc"; // Lỗi
145145
```
146146

147147

148-
## Non-enumerable
148+
## Thuộc tính "không liệt kê"
149149

150-
Now let's add a custom `toString` to `user`.
150+
Giờ thay đổi phương thức `toString` trong `user`.
151151

152-
Normally, a built-in `toString` for objects is non-enumerable, it does not show up in `for..in`. But if we add `toString` of our own, then by default it shows up in `for..in`, like this:
152+
Bình thường, thuộc tính `toString` có sẵn của các đối tượng là thuộc tính không liệt kê và không xuất hiện trong vòng lặp `for..in`. Nhưng nếu ta tự tạo phương thức `toString`, thì mặc định nó lại xuất hiện trong `for..in` như minh họa sau:
153153

154154
```js run
155155
let user = {
156-
name: "John",
156+
name: "Hùng",
157157
toString() {
158158
return this.name;
159159
}
160160
};
161161

162-
// By default, both our properties are listed:
162+
// Mặc định, cả hai thuộc tính đều được liệt kê
163163
for (let key in user) alert(key); // name, toString
164164
```
165165

166-
If we don't like it, then we can set `enumerable:false`. Then it won't appear in `for..in` loop, just like the built-in one:
166+
Nếu không muốn một thuộc tính nào đó được liệt kê, chúng ta đặt cờ `enumerable``false`. Sau đó nó không xuất hiện trong vòng lặp `for..in` nữa, giống hệt như phương thức `toString` có sẵn:
167167

168168
```js run
169169
let user = {
170-
name: "John",
170+
name: "Hùng",
171171
toString() {
172172
return this.name;
173173
}
@@ -180,24 +180,24 @@ Object.defineProperty(user, "toString", {
180180
});
181181

182182
*!*
183-
// Now our toString disappears:
183+
// Giờ toString biến mất
184184
*/!*
185185
for (let key in user) alert(key); // name
186186
```
187187

188-
Non-enumerable properties are also excluded from `Object.keys`:
188+
Các thuộc tính không liệt kê cũng bị loại khỏi `Object.keys`:
189189

190190
```js
191191
alert(Object.keys(user)); // name
192192
```
193193

194-
## Non-configurable
194+
## Thuộc tính "không thể cấu hình"
195195

196-
The non-configurable flag (`configurable:false`) is sometimes preset for built-in objects and properties.
196+
Cờ không thể cấu hình (`configurable:false`) thường được dùng cho các đối tượng và thuộc tính có sẵn.
197197

198-
A non-configurable property can not be deleted or altered with `defineProperty`.
198+
Một thuộc tính *không thể cấu hình* sẽ không thể xóa được và không thể thay đổi cờ được.
199199

200-
For instance, `Math.PI` is read-only, non-enumerable and non-configurable:
200+
Ví dụ, `Math.PI` là thuộc tính chỉ đọc, không thể cấu hình, không liệt kê:
201201

202202
```js run
203203
let descriptor = Object.getOwnPropertyDescriptor(Math, 'PI');
@@ -212,42 +212,42 @@ alert( JSON.stringify(descriptor, null, 2 ) );
212212
}
213213
*/
214214
```
215-
So, a programmer is unable to change the value of `Math.PI` or overwrite it.
215+
Cho nên lập trình viên không thể xóa cũng như thay đổi giá trị `Math.PI`, cũng không có cách nào khiến nó xuất hiện trong vòng lặp:
216216

217217
```js run
218-
Math.PI = 3; // Error
218+
Math.PI = 3; // Lỗi
219219

220-
// delete Math.PI won't work either
220+
// delete Math.PI cũng không làm việc
221221
```
222222

223-
Making a property non-configurable is a one-way road. We cannot change it back, because `defineProperty` doesn't work on non-configurable properties.
223+
Một khi làm cho một thuộc tính thành không thể cấu hình, không có cách nào khôi phục nữa bởi `defineProperty` không làm việc với chúng.
224224

225-
Here we are making `user.name` a "forever sealed" constant:
225+
Ví dụ sau, chúng ta khiến cho `user.name` thành một hằng bị "niêm phong vĩnh viễn":
226226

227227
```js run
228228
let user = { };
229229

230230
Object.defineProperty(user, "name", {
231-
value: "John",
231+
value: "Hùng",
232232
writable: false,
233233
configurable: false
234234
});
235235

236236
*!*
237-
// won't be able to change user.name or its flags
238-
// all this won't work:
239-
// user.name = "Pete"
237+
// không thể thay đổi user.name và cờ của nó
238+
// tất cả đều không làm việc:
239+
// user.name = "Mạnh"
240240
// delete user.name
241241
// defineProperty(user, "name", ...)
242-
Object.defineProperty(user, "name", {writable: true}); // Error
242+
Object.defineProperty(user, "name", {writable: true}); // Lỗi
243243
*/!*
244244
```
245245

246246
## Object.defineProperties
247247

248-
There's a method [Object.defineProperties(obj, descriptors)](mdn:js/Object/defineProperties) that allows to define many properties at once.
248+
Phương thức [Object.defineProperties(obj, descriptors)](mdn:js/Object/defineProperties) cho phép định nghĩa descriptor cho hàng loạt thuộc tính cùng lúc.
249249

250-
The syntax is:
250+
Cú pháp là:
251251

252252
```js
253253
Object.defineProperties(obj, {
@@ -257,63 +257,63 @@ Object.defineProperties(obj, {
257257
});
258258
```
259259

260-
For instance:
260+
Ví dụ:
261261

262262
```js
263263
Object.defineProperties(user, {
264-
name: { value: "John", writable: false },
265-
surname: { value: "Smith", writable: false },
264+
name: { value: "Hùng", writable: false },
265+
surname: { value: "Phùng", writable: false },
266266
// ...
267267
});
268268
```
269269

270-
So, we can set many properties at once.
270+
Nghĩa là ta có thể cài đặt "property descriptor" cho nhiều thuộc tính cùng lúc.
271271

272272
## Object.getOwnPropertyDescriptors
273273

274-
To get all property descriptors at once, we can use the method [Object.getOwnPropertyDescriptors(obj)](mdn:js/Object/getOwnPropertyDescriptors).
274+
Phương thức [Object.getOwnPropertyDescriptors(obj)](mdn:js/Object/getOwnPropertyDescriptors) cho phép lấy tất cả các descriptor của tất cả các thuộc tính.
275275

276-
Together with `Object.defineProperties` it can be used as a "flags-aware" way of cloning an object:
276+
Kết hợp với `Object.defineProperties` ta có thể nhân bản đối tượng bao gồm cả các cờ:
277277

278278
```js
279279
let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));
280280
```
281281

282-
Normally when we clone an object, we use an assignment to copy properties, like this:
282+
Thường khi nhân bản một đối tượng, chúng ta sử dụng lệnh gán để sao chép các thuộc tính:
283283

284284
```js
285285
for (let key in user) {
286286
clone[key] = user[key]
287287
}
288288
```
289289

290-
...But that does not copy flags. So if we want a "better" clone then `Object.defineProperties` is preferred.
290+
...Nhưng nó không sao chép được cờ. Vậy nên muốn nhân bản "tốt hơn" thì nên dùng `Object.defineProperties`.
291291

292-
Another difference is that `for..in` ignores symbolic properties, but `Object.getOwnPropertyDescriptors` returns *all* property descriptors including symbolic ones.
292+
Một khác biệt nữa là `for..in` bỏ qua các thuộc tính symbol, nhưng `Object.getOwnPropertyDescriptors` trả về tất cả descriptor của mọi thuộc tính kể cả symbol.
293293

294-
## Sealing an object globally
294+
## Niêm phong đối tượng
295295

296-
Property descriptors work at the level of individual properties.
296+
Sử dụng property descriptors chỉ giúp ta niêm phong từng thuộc tính.
297297

298-
There are also methods that limit access to the *whole* object:
298+
Có một số phương thức giúp ta thực hiện trên toàn đối tượng:
299299

300300
[Object.preventExtensions(obj)](mdn:js/Object/preventExtensions)
301-
: Forbids the addition of new properties to the object.
301+
: Cấm thêm các thuộc tính mới cho đối tượng.
302302

303303
[Object.seal(obj)](mdn:js/Object/seal)
304-
: Forbids adding/removing of properties. Sets `configurable: false` for all existing properties.
304+
: Cấm thêm/xóa các thuộc tính. Đặt `configurable: false` cho mọi thuộc tính.
305305

306306
[Object.freeze(obj)](mdn:js/Object/freeze)
307-
: Forbids adding/removing/changing of properties. Sets `configurable: false, writable: false` for all existing properties.
308-
And also there are tests for them:
307+
: Cấm thêm/xóa/sửa các thuộc tính. Đặt `configurable: false, writable: false` cho mọi thuộc tính.
308+
Và cũng có các phương thức kiểm tra:
309309

310310
[Object.isExtensible(obj)](mdn:js/Object/isExtensible)
311-
: Returns `false` if adding properties is forbidden, otherwise `true`.
311+
: Trả về `false` nếu không thể thêm thuộc tính cho đối tượng, nếu không trả về `true`.
312312

313313
[Object.isSealed(obj)](mdn:js/Object/isSealed)
314-
: Returns `true` if adding/removing properties is forbidden, and all existing properties have `configurable: false`.
314+
: Trả về `true` nếu không thể thêm/xóa thuộc tính, và mọi thuộc tính hiện có đều có cờ `configurable: false`.
315315

316316
[Object.isFrozen(obj)](mdn:js/Object/isFrozen)
317-
: Returns `true` if adding/removing/changing properties is forbidden, and all current properties are `configurable: false, writable: false`.
317+
: Trả về `true` nếu không thể thêm/xóa/sửa thuộc tính, và tất cả các thuộc tính hiện có đều có cờ `configurable: false, writable: false`.
318318

319-
These methods are rarely used in practice.
319+
Các phương thức này rất ít được sử dụng trong thực tế.

0 commit comments

Comments
 (0)