Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object.keys, values, entries #142

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ let salaries = {

alert( sumSalaries(salaries) ); // 650
```
Or, optionally, we could also get the sum using `Object.values` and `reduce`:
或,我們也可以使用 `Object.values` `reduce` 取得總和:

```js
// reduce loops over array of salaries,
// adding them up
// and returns the result
// reduce 遍歷整個薪水的陣列
// 把它們加總起來
// 然後傳回結果
function sumSalaries(salaries) {
return Object.values(salaries).reduce((a, b) => a + b, 0) // 650
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ importance: 5

---

# Sum the properties
# 把屬性加總

There is a `salaries` object with arbitrary number of salaries.
這裡有個 `salaries` 物件,有任意的薪水數字。

Write the function `sumSalaries(salaries)` that returns the sum of all salaries using `Object.values` and the `for..of` loop.
撰寫一個函式 `sumSalaries(salaries)`,該函式使用 `Object.values` `for..of` 迴圈來傳回全部薪水的加總。

If `salaries` is empty, then the result must be `0`.
如果 `salaries` 是空的,那麼結果必須是 `0`

For instance:
例如:

```js
let salaries = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ importance: 5

# Count properties

Write a function `count(obj)` that returns the number of properties in the object:
寫一個函式 `count(obj)`,該函式會傳回物件有幾個屬性。

```js
let user = {
Expand All @@ -15,7 +15,7 @@ let user = {
alert( count(user) ); // 2
```

Try to make the code as short as possible.
嘗試把程式碼盡可能的變短吧。

P.S. Ignore symbolic properties, count only "regular" ones.
備註:忽略符號的屬性,只計算 "一般的"。

62 changes: 31 additions & 31 deletions 1-js/05-data-types/09-keys-values-entries/article.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@

# Object.keys, values, entries

Let's step away from the individual data structures and talk about the iterations over them.
我們先忽略個別資料結構,然後來討論關於在他們上面迭代這件事情。

In the previous chapter we saw methods `map.keys()`, `map.values()`, `map.entries()`.
在前面的章節我們看過 `map.keys()``map.values()``map.entries()` 方法。

These methods are generic, there is a common agreement to use them for data structures. If we ever create a data structure of our own, we should implement them too.
這些方法是通用的,這裡通常允許資料結構去使用他們。如果我們曾經建立自有的資料結構,那我們也應該實作他們。

They are supported for:
他們可以支援:

- `Map`
- `Set`
- `Array`

Plain objects also support similar methods, but the syntax is a bit different.
一般物件也支援類似的方法,但是語法有些不同。

## Object.keys, values, entries

For plain objects, the following methods are available:
對於一般物件,有以下的方法可以使用:

- [Object.keys(obj)](mdn:js/Object/keys) -- returns an array of keys.
- [Object.values(obj)](mdn:js/Object/values) -- returns an array of values.
- [Object.entries(obj)](mdn:js/Object/entries) -- returns an array of `[key, value]` pairs.
- [Object.keys(obj)](mdn:js/Object/keys) -- 傳回鍵值陣列。
- [Object.values(obj)](mdn:js/Object/values) -- 傳回值的陣列。
- [Object.entries(obj)](mdn:js/Object/entries) -- 傳回 `[key, value]` 組成的陣列。

Please note the distinctions (compared to map for example):
請注意區別(相較於 map 的範例):

| | Map | Object |
|-------------|------------------|--------------|
| Call syntax | `map.keys()` | `Object.keys(obj)`, but not `obj.keys()` |
| Returns | iterable | "real" Array |
| 呼叫語法 | `map.keys()` | `Object.keys(obj)`,而不是 `obj.keys()` |
| 傳回 | 可迭代物件 | "實際的" 陣列 |

The first difference is that we have to call `Object.keys(obj)`, and not `obj.keys()`.
第一個區別是我們必須呼叫 `Object.keys(obj)`,而不是 `obj.keys()`

Why so? The main reason is flexibility. Remember, objects are a base of all complex structures in JavaScript. So we may have an object of our own like `data` that implements its own `data.values()` method. And we still can call `Object.values(data)` on it.
為何如此?主要原因是彈性。記住,在 JavaScript,所有複雜結構都是基於物件。所以我們可能自己有一個像是 `data` 的物件,該物件實作自有的 `data.values()` 方法。而且我們也可以對該物件呼叫 `Object.values(data)`

The second difference is that `Object.*` methods return "real" array objects, not just an iterable. That's mainly for historical reasons.
第二個區別是 `Object.*` 的方法回傳 "實際的" 陣列物件,而不只是一個可迭代物件。這主要是歷史的原因。

For instance:
例如:

```js
let user = {
Expand All @@ -49,38 +49,38 @@ let user = {
- `Object.values(user) = ["John", 30]`
- `Object.entries(user) = [ ["name","John"], ["age",30] ]`

Here's an example of using `Object.values` to loop over property values:
這裡有一個使用 `Object.values` 去遍歷所有屬性值的範例:

```js run
let user = {
name: "John",
age: 30
};

// loop over values
// 遍歷所有屬性值
for (let value of Object.values(user)) {
alert(value); // John, then 30
alert(value); // John, 然後是 30
}
```

```warn header="Object.keys/values/entries ignore symbolic properties"
Just like a `for..in` loop, these methods ignore properties that use `Symbol(...)` as keys.
```warn header="Object.keys/values/entries 會忽略符號的屬性"
就像 `for..in` 迴圈一樣,這些方法會忽略使用 `Symbol(...)` 作為鍵值的屬性。

Usually that's convenient. But if we want symbolic keys too, then there's a separate method [Object.getOwnPropertySymbols](mdn:js/Object/getOwnPropertySymbols) that returns an array of only symbolic keys. Also, there exist a method [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys.
通常來說這很方便。但是,如果我們也需要符號鍵值的話,則有一個區分的方法 [Object.getOwnPropertySymbols](mdn:js/Object/getOwnPropertySymbols),其傳回只有符號鍵值的陣列。另外,還存在一種方法 [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys),則傳回 **全部的** 鍵值。
```


## Transforming objects
## 轉換物件

Objects lack many methods that exist for arrays, e.g. `map`, `filter` and others.
物件缺乏許多存在於陣列的方法,例如 `map``filter` 等。

If we'd like to apply them, then we can use `Object.entries` followed `Object.fromEntries`:
如果我們想應用它們,那麼我們可以使用 `Object.entries` 之後使用 `Object.fromEntries`

1. Use `Object.entries(obj)` to get an array of key/value pairs from `obj`.
2. Use array methods on that array, e.g. `map`.
3. Use `Object.fromEntries(array)` on the resulting array to turn it back into an object.
1. 使用 `Object.entries(obj)` `obj` 取得鍵與值組合的陣列。
2. 在該陣列上使用陣列方法,例如 `map`
3. 在最終結果的陣列使用 `Object.fromEntries(array)` 轉回成一個物件。

For example, we have an object with prices, and would like to double them:
例如,我們有個一些價格組成的物件,然後想把它們變兩倍:

```js run
let prices = {
Expand All @@ -91,12 +91,12 @@ let prices = {

*!*
let doublePrices = Object.fromEntries(
// convert to array, map, and then fromEntries gives back the object
// 轉換成陣列,映射,然後以 fromEntries 回給物件
Object.entries(prices).map(([key, value]) => [key, value * 2])
);
*/!*

alert(doublePrices.meat); // 8
```

It may look difficult from the first sight, but becomes easy to understand after you use it once or twice. We can make powerful chains of transforms this way.
第一次看到時它看起來會很難懂,但是使用一兩次後,會變得很容易理解。我們可以用這個方式做出有力的轉換鏈式。
Loading