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

feat(loop): for...in文について #92

Merged
merged 9 commits into from
Jul 20, 2016
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"babel-preset-power-assert": "^1.0.0",
"babel-register": "^6.7.2",
"eslint": "^3.0.0",
"eslint-plugin-markdown": "^1.0.0-beta.2",
"gitbook-cli": "^2.1.2",
"gitbook-plugin-canonical-link": "^2.0.2",
"gitbook-plugin-edit-link": "^2.0.2",
Expand Down
5 changes: 5 additions & 0 deletions prh.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ rules:
- expected: シングルスレッド
patterns:
- 単一スレッド
- expected: for...in
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for...in という形式に統一してる。

patterns:
- /for\.{1,2}in/
- for-in
- for/in
# typo
- expected: $1進数
patterns:
Expand Down
81 changes: 78 additions & 3 deletions source/basic/loop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ author: azu

# ループと反復処理


プログラミングにおいて、同じ処理を繰り返すために同じコードを必要はありません。
ループや再帰呼び出し、イテレータなどを使い、反復処理は抽象化します。
ここでは、もっとも基本的な反復処理となるループについてを学んでいきます
ここでは、もっとも基本的な反復処理と制御文について学んでいきます

## while文

Expand Down Expand Up @@ -137,7 +136,7 @@ array.forEach(コールバック関数);
```

`forEach`メソッドのコールバック関数には、配列の先頭から順番に要素が渡されて実行されます。
つまり、コールバック関数の`currentValue`には1, 2, 3 …という値が順番に渡されて実行されます
つまり、コールバック関数の`currentValue`には1から5の値が順番に渡されて実行されます

```js
[1, 2, 3, 4, 5].forEach(currentValue => {
Expand Down Expand Up @@ -256,6 +255,82 @@ var filterdArray = array.filter((currentValue, index, array) => {

[import, filter-even-example.js](./src/continue/filter-even-example.js)

## for...in文

for...in文はオブジェクトのプロパティに対して、順不同で反復処理を行います。

```js
for (variable in object)
実行する文;
```

次のコードでは`object`のプロパティ名を`key`変数に代入し反復処理をしています。
`object`には、3つのプロパティ名があるため3回繰り返されます。

```js
var object = {
"a": 1,
"b": 2,
"c": 3
};
for (var key in object) {
var value = object[key];
console.log(`key:${key}, value:${value}`);
}
// key:a, value:1
// key:b, value:2
// key:c, value:3
```

オブジェクトに対する反復処理のためにfor...in文は有用に見えますが、多くの問題を持っています。

JavaScriptでは、オブジェクトは何らかのオブジェクトを継承しています。
for...in文は、対象となるオブジェクトのプロパティを列挙する場合、すべての親オブジェクトまで探索し列挙します。
そのため、オブジェクト自身が持っていないプロパティも列挙されてしまうことがあります。

この仕組みをプロトタイプチェーンといいますが、詳しくは第n章で解説します。

<!-- TODO: 第n章を埋める -->

安全にオブジェクトのプロパティを列挙するには、`Object.keys()`、`Object.values()`、`Object.entries()`などのメソッドが利用できます。

先ほどの例は、オブジェクトのキーと値を列挙するコードは次のように書くことができます。
`Object.keys()`は`object`自身がもつプロパティ名の配列を返すため、親オブジェクトのプロパティは列挙されません。

```js
var object = {
"a": 1,
"b": 2,
"c": 3
};
Object.keys(object).forEach(key => {
const value = object[key];
console.log(`key:${key}, value:${value}`);
});
// key:a, value:1
// key:b, value:2
// key:c, value:3
```

また、for...in文は配列オブジェクトに対しても利用できますが、こちらも期待した結果にはなりません。

次のコードでは、配列の要素が列挙されそうですが、実際には配列の添字が列挙されます。
つまり、配列の添字は0から始まるため、0、1という値が順番に`num`へと代入されます。

```js
var numbers = [5, 10];
var total = 0;
for (var num in numbers) {
total += num;
}
console.log(total); // => 1
```

配列の内容に対して反復処理を行う場合は、for文や`forEach`メソッド、後述するfor...of文を使うべきでしょう。

このようにfor...in文は正しく扱うのが難しいですが、代わりとなる手段が豊富にあります。
そのため、for...in文を使うことよりも他の方法を考えた方がよいでしょう。

## [コラム] `let`ではなく`const`で反復処理をする

先ほどのfor文や`forEach`メソッドでは`let`を`const`に変更することはできませでした。
Expand Down