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
Như ta đã biết, đối tượng có thể lưu các thuộc tính.
5
5
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.
7
7
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.
9
9
10
-
## Property flags
10
+
## Các "cờ" của thuộc tính
11
11
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à:
13
13
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ó.
17
17
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.
19
19
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:
21
21
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ị).
23
23
24
-
The syntax is:
24
+
Cú pháp là:
25
25
```js
26
26
let descriptor =Object.getOwnPropertyDescriptor(obj, propertyName);
27
27
```
28
28
29
29
`obj`
30
-
: The object to get information from.
30
+
: Là đối tượng chứa thuộc tính.
31
31
32
32
`propertyName`
33
-
: The name of the property.
33
+
: Là tên thuộc tính.
34
34
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**.
36
36
37
-
For instance:
37
+
Ví dụ:
38
38
39
39
```js run
40
40
let user = {
41
-
name:"John"
41
+
name:"Hùng"
42
42
};
43
43
44
44
let descriptor =Object.getOwnPropertyDescriptor(user, 'name');
45
45
46
46
alert( JSON.stringify(descriptor, null, 2 ) );
47
47
/* property descriptor:
48
48
{
49
-
"value": "John",
49
+
"value": "Hùng",
50
50
"writable": true,
51
51
"enumerable": true,
52
52
"configurable": true
53
53
}
54
54
*/
55
55
```
56
56
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).
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`.
72
72
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`:
74
74
75
75
```js run
76
76
let user = {};
77
77
78
78
*!*
79
79
Object.defineProperty(user, "name", {
80
-
value:"John"
80
+
value:"Hùng"
81
81
});
82
82
*/!*
83
83
@@ -86,7 +86,7 @@ let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
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`.
100
100
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ụ.
102
102
103
-
## Read-only
103
+
## Thuộc tính "chỉ đọc"
104
104
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`là `false`:
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'...
120
120
*/!*
121
121
```
122
122
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.
124
124
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.
127
127
```
128
128
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:
130
130
131
131
```js run
132
132
let user = { };
133
133
134
134
Object.defineProperty(user, "name", {
135
135
*!*
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
138
138
enumerable:true,
139
139
configurable:true
140
140
*/!*
141
141
});
142
142
143
-
alert(user.name); //Pete
144
-
user.name="Alice"; //Error
143
+
alert(user.name); //Hùng
144
+
user.name="Ngọc"; //Lỗi
145
145
```
146
146
147
147
148
-
## Non-enumerable
148
+
## Thuộc tính "không liệt kê"
149
149
150
-
Now let's add a custom`toString`to`user`.
150
+
Giờ thay đổi phương thức`toString`trong`user`.
151
151
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:
153
153
154
154
```js run
155
155
let user = {
156
-
name:"John",
156
+
name:"Hùng",
157
157
toString() {
158
158
returnthis.name;
159
159
}
160
160
};
161
161
162
-
//By default, both our properties are listed:
162
+
//Mặc định, cả hai thuộc tính đều được liệt kê
163
163
for (let key in user) alert(key); // name, toString
164
164
```
165
165
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` là `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:
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.
Nghĩa là ta có thể cài đặt "property descriptor" cho nhiều thuộc tính cùng lúc.
271
271
272
272
## Object.getOwnPropertyDescriptors
273
273
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.
275
275
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ờ:
277
277
278
278
```js
279
279
let clone =Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));
280
280
```
281
281
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:
283
283
284
284
```js
285
285
for (let key in user) {
286
286
clone[key] = user[key]
287
287
}
288
288
```
289
289
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`.
291
291
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.
293
293
294
-
## Sealing an object globally
294
+
## Niêm phong đối tượng
295
295
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.
297
297
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:
0 commit comments