diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md index ed8a3f4d7..c45c793be 100644 --- a/1-js/04-object-basics/01-object/article.md +++ b/1-js/04-object-basics/01-object/article.md @@ -1,60 +1,62 @@ -# Objects +# Đối tượng -As we know from the chapter , there are eight data types in JavaScript. Seven of them are called "primitive", because their values contain only a single thing (be it a string or a number or whatever). +Như chúng ta đã biết ở chương , có tám loại dữ liệu trong JavaScript. Bảy trong số chúng được gọi là "nguyên thủy", bởi vì giá trị của chúng chỉ chứa một thứ duy nhất (đó có thể là một chuỗi hoặc một số hoặc cái gì đó khác). -In contrast, objects are used to store keyed collections of various data and more complex entities. In JavaScript, objects penetrate almost every aspect of the language. So we must understand them first before going in-depth anywhere else. +Ngược lại, các đối tượng được sử dụng để lưu trữ các bộ sưu tập có khóa của các dữ liệu khác nhau và các thực thể phức tạp hơn. Trong JavaScript, các đối tượng thâm nhập vào hầu hết mọi khía cạnh của ngôn ngữ. Vì vậy, chúng ta phải hiểu chúng trước khi đi sâu vào bất cứ nơi nào khác. -An object can be created with figure brackets `{…}` with an optional list of *properties*. A property is a "key: value" pair, where `key` is a string (also called a "property name"), and `value` can be anything. +Một đối tượng có thể được tạo bằng dấu ngoặc hình `{…}` với một danh sách *thuộc tính* tùy chọn. Một thuộc tính là một cặp "khóa: giá trị", trong đó `khóa` là một chuỗi (còn được gọi là "tên thuộc tính"), và `giá trị` có thể là bất cứ thứ gì. -We can imagine an object as a cabinet with signed files. Every piece of data is stored in its file by the key. It's easy to find a file by its name or add/remove a file. +Chúng ta có thể tưởng tượng một đối tượng như một cái tủ với các tập tin đã ký. Mỗi phần dữ liệu được lưu trữ trong tệp của nó bằng từ khóa. Thật dễ dàng để tìm một tệp theo tên của nó hoặc thêm/xóa một tệp. ![](object.svg) -An empty object ("empty cabinet") can be created using one of two syntaxes: +Một đối tượng rỗng ("tủ rỗng") có thể được tạo bằng một hoặc hai cú pháp: ```js -let user = new Object(); // "object constructor" syntax -let user = {}; // "object literal" syntax +let user = new Object(); // cú pháp "đối tượng constructor" +let user = {}; // cú pháp "đối tượng theo nghĩa đen" ``` ![](object-user-empty.svg) -Usually, the figure brackets `{...}` are used. That declaration is called an *object literal*. +Thông thường, dấu ngoặc `{...}` được sử dụng. Loại khai báo đó được gọi là *đối tượng theo nghĩa đen*. -## Literals and properties +## Đối tượng theo nghĩa đen và thuộc tính -We can immediately put some properties into `{...}` as "key: value" pairs: +Chúng ta có thể ngay lập tức đặt một số thuộc tính vào `{...}` dưới dạng các cặp "khóa: giá trị": ```js -let user = { // an object - name: "John", // by key "name" store value "John" - age: 30 // by key "age" store value 30 +let user = { // một đối tượng + name: "John", // khóa "name" lưu giá trị "John" + age: 30 // khóa "age" lưu giá trị 30 }; ``` -A property has a key (also known as "name" or "identifier") before the colon `":"` and a value to the right of it. +Một thuộc tính có một khóa (còn được gọi là "tên" hoặc "định danh") trước dấu hai chấm `":"` và một giá trị ở bên phải của nó. -In the `user` object, there are two properties: +Trong đối tượng `user`, có hai thuộc tính: -1. The first property has the name `"name"` and the value `"John"`. -2. The second one has the name `"age"` and the value `30`. +1. Thuộc tính thứ nhất có tên là `"name"` và giá trị là `"John"`. +2. Thuộc tính thứ hai có tên là `"age"` và giá trị là `30`. The resulting `user` object can be imagined as a cabinet with two signed files labeled "name" and "age". +Kết quả là đối tượng `user` có thể được tưởng tượng như một cái tủ với hai tệp được ký có nhãn "name" và "age". + ![user object](object-user.svg) -We can add, remove and read files from it any time. +Chúng ta có thể thêm, xóa và đọc tệp từ chúng mọi lúc. -Property values are accessible using the dot notation: +Các giá trị của thuộc tính có thể truy cập bằng cách sử dụng dấu chấm: ```js -// get property values of the object: +// lấy giá trị của thuộc tính trong đối tượng: alert( user.name ); // John alert( user.age ); // 30 ``` -The value can be of any type. Let's add a boolean one: +Giá trị có thể là bất kỳ kiểu dữ liệu nào. Hãy thêm một giá trị boolean: ```js user.isAdmin = true; @@ -62,7 +64,7 @@ user.isAdmin = true; ![user object 2](object-user-isadmin.svg) -To remove a property, we can use `delete` operator: +Để xóa thuộc tính, ta có thể dùng `delete`: ```js delete user.age; @@ -70,42 +72,42 @@ delete user.age; ![user object 3](object-user-delete.svg) -We can also use multiword property names, but then they must be quoted: +Chúng ta cũng có thể sử dụng tên thuộc tính có nhiều từ, nhưng sau đó chúng phải được bọc lại: ```js let user = { name: "John", age: 30, - "likes birds": true // multiword property name must be quoted + "likes birds": true // tên thuộc tính nhiều từ phải được bọc lại bằng dấu ngoặc kép }; ``` ![](object-user-props.svg) -The last property in the list may end with a comma: +Thuộc tính cuối cùng trong danh sách có thể kết thúc bằng dấu phẩy: ```js let user = { name: "John", age: 30*!*,*/!* } ``` -That is called a "trailing" or "hanging" comma. Makes it easier to add/remove/move around properties, because all lines become alike. +Đó được gọi là dấu phẩy "trailing" hay "hanging". Nó khiến dễ dàng thêm/xóa/di chuyển xung quanh các thuộc tính, bởi vì tất cả các dòng trở nên giống nhau. -## Square brackets +## Dấu ngoặc vuông -For multiword properties, the dot access doesn't work: +Với thuộc tính nhiều từ, truy cập bằng dấu chấm không hoạt động: ```js run -// this would give a syntax error +// sẽ có lỗi cú pháp user.likes birds = true ``` -JavaScript doesn't understand that. It thinks that we address `user.likes`, and then gives a syntax error when comes across unexpected `birds`. +JavaScript không hiểu điều đó. Nó nghĩ rằng chúng ta cần `user.likes`, do đó nó trả ra lỗi cú pháp khi đi qua `birds` không mong muốn. -The dot requires the key to be a valid variable identifier. That implies: contains no spaces, doesn't start with a digit and doesn't include special characters (`$` and `_` are allowed). +Dấu chấm yêu cầu khóa phải là một biến định danh hợp lệ. Đó là: không chứa khoảng trắng, không bắt đầu bằng một số và không bao gồm các kí tự đặc biệt (`$` và `_` thì được). -There's an alternative "square bracket notation" that works with any string: +Có một thay thế là "dấu ngoặc vuông" sẽ hoạt động với bất cứ chuỗi nào: ```js run let user = {}; @@ -120,20 +122,20 @@ alert(user["likes birds"]); // true delete user["likes birds"]; ``` -Now everything is fine. Please note that the string inside the brackets is properly quoted (any type of quotes will do). +Bây giờ mọi thứ đã tốt. Hãy lưu ý rằng chuỗi bên trong ngoặc được bao bọc chính xác (bất kỳ loại bao bọc nào cũng được). -Square brackets also provide a way to obtain the property name as the result of any expression -- as opposed to a literal string -- like from a variable as follows: +Dấu ngoặc vuông cũng cung cấp một cách để có được tên thuộc tính là kết quả của bất kỳ biểu thức nào -- trái ngược với chuỗi ký tự -- giống như từ một biến như sau: ```js let key = "likes birds"; -// same as user["likes birds"] = true; +// giống như user["likes birds"] = true; user[key] = true; ``` -Here, the variable `key` may be calculated at run-time or depend on the user input. And then we use it to access the property. That gives us a great deal of flexibility. +Ở đây, biến `key` có thể được tính vào thời gian chạy hoặc phụ thuộc vào đầu vào của người dùng. Và sau đó chúng ta sử dụng nó để truy cập vào thuộc tính. Điều đó giúp chúng ta linh hoạt hơn. -For instance: +Ví dụ: ```js run let user = { @@ -141,13 +143,13 @@ let user = { age: 30 }; -let key = prompt("What do you want to know about the user?", "name"); +let key = prompt("Bạn muốn biết điều gì về người dùng?", "name"); -// access by variable -alert( user[key] ); // John (if enter "name") +// truy cập vào biến +alert( user[key] ); // John (nếu nhập "name") ``` -The dot notation cannot be used in a similar way: +Dấu chấm không thể dùng theo cách như vậy: ```js run let user = { @@ -159,40 +161,40 @@ let key = "name"; alert( user.key ) // undefined ``` -### Computed properties +### Thuộc tính computed -We can use square brackets in an object literal, when creating an object. That's called *computed properties*. +Chúng ta có thể sử dụng dấu ngoặc vuông trong một object literal, khi tạo một object. Đó gọi là * những thuộc tính computed*. -For instance: +Ví dụ: ```js run -let fruit = prompt("Which fruit to buy?", "apple"); +let fruit = prompt("Mua loại trái cây nào?", "apple"); let bag = { *!* - [fruit]: 5, // the name of the property is taken from the variable fruit + [fruit]: 5, // tên của thuộc tính được lấy từ biến fruit */!* }; -alert( bag.apple ); // 5 if fruit="apple" +alert( bag.apple ); // 5 nếu fruit="apple" ``` -The meaning of a computed property is simple: `[fruit]` means that the property name should be taken from `fruit`. +Ý nghĩa của thuộc tính computed rất đơn giản: `[fruit]` có nghĩa là tên thuộc tính nên được lấy từ` fruit`. -So, if a visitor enters `"apple"`, `bag` will become `{apple: 5}`. +Do vậy, nếu người dùng nhập `"apple"`, `bag` sẽ thành `{apple: 5}`. -Essentially, that works the same as: +Về cơ bản, nó hoạt động giống như: ```js run -let fruit = prompt("Which fruit to buy?", "apple"); +let fruit = prompt("Mua loại trái cây nào?", "apple"); let bag = {}; -// take property name from the fruit variable +// lấy tên thuộc tính từ biến fruit bag[fruit] = 5; ``` -...But looks nicer. +...Nhưng nhìn tốt hơn. -We can use more complex expressions inside square brackets: +Chúng ta có thể sử dụng các biểu thức phức tạp hơn trong dấu ngoặc vuông: ```js let fruit = 'apple'; @@ -201,22 +203,22 @@ let bag = { }; ``` -Square brackets are much more powerful than the dot notation. They allow any property names and variables. But they are also more cumbersome to write. +Dấu ngoặc vuông có mạnh hơn dấu chấm. Chúng chấp nhận bất cứ tên của thuộc tính và biến nào. Nhưng ngoài ra chúng cũng cồng kềnh khi viết. -So most of the time, when property names are known and simple, the dot is used. And if we need something more complex, then we switch to square brackets. +Vì vậy hầu hết thời gian, khi tên thuộc tính được biết và đơn giản, dấu chấm được sử dụng. Và nếu chúng ta cần một cái gì đó phức tạp hơn, thì chúng ta chuyển sang dấu ngoặc vuông. ## Property value shorthand -In real code we often use existing variables as values for property names. +Trong code chúng ta thường sử dụng các biến sẵn có làm giá trị cho tên của các thuộc tính. -For instance: +Ví dụ: ```js run function makeUser(name, age) { return { name: name, age: age, - // ...other properties + // ...các thuộc tính khác }; } @@ -224,40 +226,39 @@ let user = makeUser("John", 30); alert(user.name); // John ``` -In the example above, properties have the same names as variables. The use-case of making a property from a variable is so common, that there's a special *property value shorthand* to make it shorter. +Trong ví dụ trên, các thuộc tính có cùng tên với các biến. Trường hợp sử dụng để tạo một thuộc tính từ một biến là rất phổ biến, do đó có một loại *tốc ký giá trị của thuộc tính* làm cho nó ngắn hơn. -Instead of `name:name` we can just write `name`, like this: +Thay vì `name:name` chúng ta có thể viết `name`, như thế này: ```js function makeUser(name, age) { *!* return { - name, // same as name: name - age, // same as age: age + name, // giống như name: name + age, // giống như age: age // ... }; */!* } ``` -We can use both normal properties and shorthands in the same object: +Chúng ta có thể sử dụng cả thuộc tính bình thường và tốc ký trong cùng một đối tượng: ```js let user = { - name, // same as name:name + name, // giống như name:name age: 30 }; ``` +## Giới hạn của tên thuộc tính -## Property names limitations - -As we already know, a variable cannot have a name equal to one of language-reserved words like "for", "let", "return" etc. +Như ta đã biết, một biến không thể có tên trùng với những từ dành riêng cho ngôn ngữ lập trình như "for", "let", "return" vâng vâng. -But for an object property, there's no such restriction: +Nhưng thuộc tính của object thì không giới hạn: ```js run -// these properties are all right +// những thuộc tính này đều đúng let obj = { for: 1, let: 2, @@ -267,23 +268,23 @@ let obj = { alert( obj.for + obj.let + obj.return ); // 6 ``` -In short, there are no limitations on property names. They can be any strings or symbols (a special type for identifiers, to be covered later). +Nói tóm lại, không có giới hạn về tên thuộc tính. Chúng có thể là bất kỳ chuỗi hoặc ký hiệu nào (có một loại đặc biệt dành cho nhận dạng, sẽ được đề cập sau). -Other types are automatically converted to strings. +Các loại khác được tự động chuyển thành chuỗi. -For instance, a number `0` becomes a string `"0"` when used as a property key: +Chẳng hạn, số `0` trở thành một chuỗi `"0"` khi được sử dụng làm khóa thuộc tính: ```js run let obj = { - 0: "test" // same as "0": "test" + 0: "test" // giống như "0": "test" }; -// both alerts access the same property (the number 0 is converted to string "0") +// cả hai alert đều truy cập vào cùng một thuộc tính (số 0 được chuyển đổi thành chuỗi "0") alert( obj["0"] ); // test -alert( obj[0] ); // test (same property) +alert( obj[0] ); // test (có cùng thuộc tính) ``` -There's a minor gotcha with a special property named `__proto__`. We can't set it to a non-object value: +Có một vấn đề nhỏ với thuộc tính đặc biệt có tên `__proto__`. Chúng ta không thể đặt nó thành non-object value: ```js run let obj = {}; @@ -291,83 +292,83 @@ obj.__proto__ = 5; // assign a number alert(obj.__proto__); // [object Object] - the value is an object, didn't work as intended ``` -As we see from the code, the assignment to a primitive `5` is ignored. +Như chúng ta thấy từ code, việc gán cho số `5` bị bỏ qua. -We'll cover the special nature of `__proto__` in [subsequent chapters](info:prototype-inheritance), and suggest the [ways to fix](info:prototype-methods) such behavior. +Chúng ta sẽ đề cập đến bản chất đặc biệt của `__proto__` trong [các chương tiếp theo](info:prototype-inheritance) và đề xuất [các cách khắc phục](info:prototype-methods) hành vi như vậy. -## Property existence test, "in" operator +## Kiểm tra sự tồn tại của thuộc tính, toán tử "in" -A notable feature of objects in JavaScript, compared to many other languages, is that it's possible to access any property. There will be no error if the property doesn't exist! +Một tính năng đáng chú ý của các đối tượng trong JavaScript, so với nhiều ngôn ngữ khác, là có thể truy cập bất kỳ thuộc tính nào. Sẽ không có lỗi nếu thuộc tính không tồn tại! -Reading a non-existing property just returns `undefined`. So we can easily test whether the property exists: +Việc truy cập thuộc tính không tồn tại chỉ trả về `undefined`. Vì vậy, chúng ta có thể dễ dàng kiểm tra xem thuộc tính có tồn tại hay không: ```js run let user = {}; -alert( user.noSuchProperty === undefined ); // true means "no such property" +alert( user.noSuchProperty === undefined ); // true có nghĩa là "no such property" ``` -There's also a special operator `"in"` for that. +Ngoài ra còn tồn tại một toán tử đặc biệt `"in"` cho điều đó. -The syntax is: +Cú pháp: ```js "key" in object ``` -For instance: +Ví dụ: ```js run let user = { name: "John", age: 30 }; -alert( "age" in user ); // true, user.age exists -alert( "blabla" in user ); // false, user.blabla doesn't exist +alert( "age" in user ); // true, user.age tồn tại +alert( "blabla" in user ); // false, user.blabla không tồn tại ``` -Please note that on the left side of `in` there must be a *property name*. That's usually a quoted string. +Hãy lưu ý rằng ở phía bên trái của `in` phải có *tên thuộc tính*. Đó thường là một chuỗi được bao bọc trong dấu ngoặc kép. -If we omit quotes, that means a variable, it should contain the actual name to be tested. For instance: +Nếu chúng ta bỏ qua dấu ngoặc kép, điều đó có nghĩa là một biến chứa tên thực tế sẽ được kiểm tra. Ví dụ: ```js run let user = { age: 30 }; let key = "age"; -alert( *!*key*/!* in user ); // true, property "age" exists + +alert( *!*key*/!* in user ); // true, thuộc tính "age" tồn tại ``` -Why does the `in` operator exist? Isn't it enough to compare against `undefined`? +Tại sao `in` tồn tại? Không phải nó quá đủ để so sánh `undefined` sao? -Well, most of the time the comparison with `undefined` works fine. But there's a special case when it fails, but `"in"` works correctly. +Vâng, thường thì so sánh với `undefined` là đủ. Nhưng có một trường hợp đặc biệt khi nó lỗi, nhưng `"in"` hoạt động đúng. -It's when an object property exists, but stores `undefined`: +Đó là khi một thuộc tính trong đối tượng tồn tại, nhưng lưu trữ là `undefined`: ```js run let obj = { test: undefined }; -alert( obj.test ); // it's undefined, so - no such property? +alert( obj.test ); // thuộc tính không tồn tại, do đó - nó không phải là thuộc tính? -alert( "test" in obj ); // true, the property does exist! +alert( "test" in obj ); // true, thuộc tính tồn tại! ``` -In the code above, the property `obj.test` technically exists. So the `in` operator works right. +Trong đoạn code trên, về mặt kỹ thuật thuộc tính `obj.test` tồn tại. Vì vậy, toán tử `in` hoạt động đúng. -Situations like this happen very rarely, because `undefined` should not be explicitly assigned. We mostly use `null` for "unknown" or "empty" values. So the `in` operator is an exotic guest in the code. +Các tình huống như thế này rất hiếm khi xảy ra, vì `undefined` thường không được chỉ định. Chúng ta chủ yếu sử dụng `null` cho các giá trị "không xác định" hoặc "rỗng". Vì vậy, toán tử `in` là một vị khách kỳ lạ trong code. +## Vòng lặp "for..in" -## The "for..in" loop +Để đi qua tất cả các khóa của một đối tượng, ta có một dạng vòng lặp đặc biệt: `for..in`. Đây là một điều hoàn toàn khác với cấu trúc `for (;;)` mà chúng ta đã học trước đây. -To walk over all keys of an object, there exists a special form of the loop: `for..in`. This is a completely different thing from the `for(;;)` construct that we studied before. - -The syntax: +Cú pháp: ```js for (key in object) { - // executes the body for each key among object properties + // thực thi phần thân cho mỗi key của thuộc tính trong đối tượng } ``` -For instance, let's output all properties of `user`: +Ví dụ, in ra tất cả các thuộc tính của `user`: ```js run let user = { @@ -377,32 +378,33 @@ let user = { }; for (let key in user) { - // keys + // các khóa alert( key ); // name, age, isAdmin - // values for the keys + // giá trị của các khóa alert( user[key] ); // John, 30, true } ``` -Note that all "for" constructs allow us to declare the looping variable inside the loop, like `let key` here. +Lưu ý rằng tất cả các cấu trúc "for" cho phép chúng ta khai báo biến vòng lặp bên trong vòng lặp, như `let key` ở đây. + +Ngoài ra, chúng ta có thể sử dụng một tên biến khác ở đây thay vì `key`. Chẳng hạn, `"for (let prop in obj)"` cũng được sử dụng rộng rãi. -Also, we could use another variable name here instead of `key`. For instance, `"for (let prop in obj)"` is also widely used. -### Ordered like an object +### Sắp xếp như một đối tượng -Are objects ordered? In other words, if we loop over an object, do we get all properties in the same order they were added? Can we rely on this? +Đối tượng có được sắp xếp không? Nói cách khác, nếu chúng ta lặp qua một đối tượng, chúng ta có nhận được tất cả các thuộc tính theo cùng thứ tự chúng đã được thêm không? Chúng ta có thể tin vào điều này không? -The short answer is: "ordered in a special fashion": integer properties are sorted, others appear in creation order. The details follow. +Câu trả lời là: "sắp xếp theo kiểu đặc biệt": thuộc tính số nguyên được sắp xếp, những cái khác xuất hiện theo thứ tự tạo. Các chi tiết theo sau. -As an example, let's consider an object with the phone codes: +Ví dụ: hãy xem xét một đối tượng có chứa mã điện thoại: ```js run let codes = { - "49": "Germany", - "41": "Switzerland", - "44": "Great Britain", + "49": "Đức", + "41": "Thụy Sĩ", + "44": "Anh", // .., - "1": "USA" + "1": "Mỹ" }; *!* @@ -412,56 +414,56 @@ for (let code in codes) { */!* ``` -The object may be used to suggest a list of options to the user. If we're making a site mainly for German audience then we probably want `49` to be the first. +Đối tượng có thể được sử dụng để đề xuất một danh sách các tùy chọn cho người dùng. Nếu chúng ta tạo một trang chủ yếu cho người Đức thì có lẽ chúng ta muốn `49` đứng đầu tiên. -But if we run the code, we see a totally different picture: +Nhưng nếu chúng ta chạy code, chúng ta sẽ thấy một bức tranh hoàn toàn khác: -- USA (1) goes first -- then Switzerland (41) and so on. +- Mỹ (1) đứng đầu +- sau đó Thụy Sỹ (41) và cứ thế. -The phone codes go in the ascending sorted order, because they are integers. So we see `1, 41, 44, 49`. +Các mã điện thoại đi theo thứ tự tăng dần, bởi vì chúng là số nguyên. Vì vậy, chúng ta thấy `1, 41, 44, 49`. ````smart header="Integer properties? What's that?" -The "integer property" term here means a string that can be converted to-and-from an integer without a change. +Thuật ngữ "thuộc tính số nguyên" ở đây có nghĩa là một chuỗi có thể được chuyển đổi thành và từ một số nguyên mà không thay đổi. -So, "49" is an integer property name, because when it's transformed to an integer number and back, it's still the same. But "+49" and "1.2" are not: +Do đó, "49" là thuộc thuộc tính số nguyên, vì khi nó được chuyển đổi sang số nguyên và ngược lại, nó vẫn giống nhau. Nhưng "+49" và "1.2" thì không: ```js run -// Math.trunc is a built-in function that removes the decimal part -alert( String(Math.trunc(Number("49"))) ); // "49", same, integer property -alert( String(Math.trunc(Number("+49"))) ); // "49", not same "+49" ⇒ not integer property -alert( String(Math.trunc(Number("1.2"))) ); // "1", not same "1.2" ⇒ not integer property +// Math.trunc là một hàm dựng sẵn để xóa một phần của số thập phân +alert( String(Math.trunc(Number("49"))) ); // "49", giống nhau, thuộc tính số nguyên +alert( String(Math.trunc(Number("+49"))) ); // "49", không giống "+49" ⇒ không phải thuộc tính số nguyên +alert( String(Math.trunc(Number("1.2"))) ); // "1", không giống "1.2" ⇒ không phải thuộc tính số nguyên ``` ```` -...On the other hand, if the keys are non-integer, then they are listed in the creation order, for instance: +...Mặt khác, nếu các khóa không phải là số nguyên, thì chúng được liệt kê theo thứ tự tạo, Ví dụ: ```js run let user = { name: "John", surname: "Smith" }; -user.age = 25; // add one more +user.age = 25; // thêm một thuộc tính nữa *!* -// non-integer properties are listed in the creation order +// thuộc tính không nguyên được liệt kê theo thứ tự tạo */!* for (let prop in user) { alert( prop ); // name, surname, age } ``` -So, to fix the issue with the phone codes, we can "cheat" by making the codes non-integer. Adding a plus `"+"` sign before each code is enough. +Vì vậy, để khắc phục sự cố với mã điện thoại, chúng ta có thể "gian lận" bằng cách làm cho mã không nguyên. Thêm dấu cộng `"+"` trước mỗi mã là đủ. -Like this: +Như sau: ```js run let codes = { - "+49": "Germany", - "+41": "Switzerland", - "+44": "Great Britain", + "+49": "Đức", + "+41": "Thụy Sỹ", + "+44": "Anh", // .., - "+1": "USA" + "+1": "Mỹ" }; for (let code in codes) { @@ -469,34 +471,34 @@ for (let code in codes) { } ``` -Now it works as intended. +Bây giờ nó hoạt động như ý muốn. -## Summary +## Tổng kết -Objects are associative arrays with several special features. +Đối tượng là mảng kết hợp với một số tính năng đặc biệt. -They store properties (key-value pairs), where: -- Property keys must be strings or symbols (usually strings). -- Values can be of any type. +Họ lưu trữ các thuộc tính (các cặp khóa-giá trị), trong đó: +- Thuộc tính khóa phải là chuỗi hoặc ký hiệu (thường là chuỗi). +- Giá trị có thể là bất kỳ loại nào. -To access a property, we can use: -- The dot notation: `obj.property`. -- Square brackets notation `obj["property"]`. Square brackets allow to take the key from a variable, like `obj[varWithKey]`. +Để truy cập một thuộc tính, chúng ta có thể sử dụng: +- Ký hiệu dấu chấm: `obj.property`. +- Ký hiệu ngoặc vuông `obj["property"]`. Dấu ngoặc vuông cho phép lấy khóa từ một biến, như `obj[varWithKey]`. -Additional operators: -- To delete a property: `delete obj.prop`. -- To check if a property with the given key exists: `"key" in obj`. -- To iterate over an object: `for (let key in obj)` loop. +Toán tử bổ sung: +- Để xóa một thuộc tính: `delete obj.prop`. +- Để kiểm tra xem một thuộc tính có khóa đã cho có tồn tại không: `"key" in obj`. +- Để lặp qua một đối tượng: `for (let key in obj)` -What we've studied in this chapter is called a "plain object", or just `Object`. +Những gì chúng ta đã nghiên cứu trong chương này được gọi là "đối tượng đơn giản", hoặc `Object`. -There are many other kinds of objects in JavaScript: +Có nhiều loại đối tượng khác trong JavaScript: -- `Array` to store ordered data collections, -- `Date` to store the information about the date and time, -- `Error` to store the information about an error. -- ...And so on. +- `Array` để lưu trữ các bộ sưu tập dữ liệu theo thứ tự, +- `Ngày` để lưu trữ thông tin về ngày và giờ, +- `Error` để lưu trữ thông tin về lỗi. +- ...Và nhiều hơn. -They have their special features that we'll study later. Sometimes people say something like "Array type" or "Date type", but formally they are not types of their own, but belong to a single "object" data type. And they extend it in various ways. +Chúng có những tính năng đặc biệt mà chúng ta sẽ nghiên cứu sau. Đôi khi mọi người nói một cái gì đó như "Kiểu mảng" hoặc "Kiểu ngày", nhưng chính thức chúng không có kiểu của riêng chúng, mà thuộc về một loại dữ liệu "đối tượng" duy nhất. Và chúng mở rộng nó theo nhiều cách khác nhau. -Objects in JavaScript are very powerful. Here we've just scratched the surface of a topic that is really huge. We'll be closely working with objects and learning more about them in further parts of the tutorial. +Các đối tượng trong JavaScript rất mạnh mẽ. Chúng ta chỉ vừa vạch ra bề mặt của một chủ đề thực sự rất lớn. Ta sẽ làm việc chặt chẽ với các đối tượng và tìm hiểu thêm về chúng trong các phần tiếp theo.