かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

JavaScript (ES2015) オブジェクトのループについてのメモ

ES2016/ES6でfor...ofが追加されたので改めてオブジェクトのループの方法を見直そうと思いました。

for..of

for...of 文は、iterableオブジェクトに対して反復的な処理をするループを作成します(iterableオブジェクトには組み込みのString, Array, 例えば Array に似たargumentsNodeListオブジェクト、TypedArray, Map, Set, ユーザー定義のiterableなどが含まれます)。

for..of と for...in の違い

  • for...of は値を列挙する
  • for...in はプロパティ(インデックス)を "prototypeで拡張されたプロパティを含めて" 列挙する

ex

Object.prototype.objCustomFunc = function() {};
Array.prototype.arrCustomFunc = function() {};
let arr = ['星宮いちご', '霧矢あおい', '紫吹蘭'];
arr.unitName = 'ソレイユ';

// for...of
for (let val of arr) {
  console.log(val);
}
// => "星宮いちご", "霧矢あおい", "紫吹蘭"

// for...in
for (let i in arr) {
  console.log(i);
}
// => 0, 1, 2, "unitName", "arrCustomFunc", "objCustomFunc"

// hasOwnProperty を使えば自身のプロパティだけに限定できる
for (let i in arr) {
  if ( iterable.hasOwnProperty(i) ) {
    console.log(i);
  }
}
// => 0, 1, 2, "unitName"

for...of でオブジェクトをそのままループさせることはできない

ObjectはiterableオブジェクトではないのでTypeErrorになる

let obj = {
  cute:   '星宮いちご',
  cool:   '霧矢あおい',
  sexy:   '紫吹蘭',
  pop:    '夏樹みくる',
  legend: '神前美月'
};
for (let val of obj) {
  console.log(val);
}
// => TypeError: obj is not iterable

Object.keys()でキーの配列をfor...ofでループさせる

let obj = {
  cute:   '星宮いちご',
  cool:   '霧矢あおい',
  sexy:   '紫吹蘭',
  pop:    '夏樹みくる',
  legend: '神前美月'
};
Object.prototype.objCustomFunc = function() {};

// for...of Object.keys(obj)
for (let key of Object.keys(obj)) {
  console.log(key, obj[key]);
}
// cute 星宮いちご
// cool 霧矢あおい
// sexy 紫吹蘭
// pop 夏樹みくる
// legend 神前美月

Array.forEachを使う方法

Object.keys(obj).forEach(function(key) {
  console.log(key, this[key]);
}, obj);
// cute 星宮いちご
// cool 霧矢あおい
// sexy 紫吹蘭
// pop 夏樹みくる
// legend 神前美月

Array.forEachで実行する関数をアロー関数()=>にすると、関数内のthisが第二引数で渡したオブジェクトにならないので、第二引数を使用する場合は注意が必要

for...in obj を使う方法

for...inならオブジェクトのままループさせることができるが、配列と同様でprototypeで拡張されたプロパティも列挙される

for (let key in obj) {
  console.log(key, obj[key]);
}
// cute 星宮いちご
// cool 霧矢あおい
// sexy 紫吹蘭
// pop 夏樹みくる
// legend 神前美月
// objCustomFunc [Function]
所謂 for 文でループさせる
let keys = Object.keys(obj);
for (let i = 0, l = keys.length; i < l; i += 1) {
  console.log(keys[i], obj[ keys[i] ]);
}
// cute 星宮いちご
// cool 霧矢あおい
// sexy 紫吹蘭
// pop 夏樹みくる
// legend 神前美月

まとめ

オブジェクトをループさせたい時

  1. for...of Object.keys(obj) でループさせる
  2. Object.keys(obj).forEach でループさせる ※ ループ中にbreakはできない
  3. for...in obj でループさせ適時 obj.hasOwnProperty(key)で自身のプロパティかチェックする
  4. for文でオブジェクトのキーをインデックス順に列挙してループさせる

ループ中にbreakもできるのでES2015/ES6が使える環境なら、for...ofでループさせるのが一番ラクかなと思いました。
IEfor...of未対応なようなので、IE11必須みたいなWEBサイト制作ではbabelとか使わないとダメですね... IE... ξ(Ծ‸Ծ)ξ


[参考]

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

JavaScript (ES2015) 分割代入でセミコロンがないとエラーになるトラップにはまる。

ECMAScript2015 (ES2015 / ES6)で追加された、配列やオブジェクトを分割して変数に代入できる分割代入で色々エラーになってハマったのでメモ。

分割代入 Destructuring assignment

分割代入 - JavaScript | MDN とは

// 配列
let [a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]

// オブジェクト
let {cute, cool, sexy, ...other} = {
  cute:   '星宮いちご',
  cool:   '霧矢あおい',
  pop:    '有栖川おとめ',
  sexy:   '紫吹蘭',
  legend: '神前美月'
};
console.log(cute);  // 星宮いちご
console.log(cool);  // 霧矢あおい
console.log(sexy);  // 紫吹蘭
console.log(other); // { pop: '有栖川おとめ', legend: '神前美月' }

こんなの。
配列は前から順番(インデックス順)に、オブジェクトは変数名と合致するプロパティの値が変数に代入される。

変数宣言外で分割代入をする際のトラップ

オブジェクトの分割代入を行う時、全体を()で囲ってないとエラーになる

変数宣言とオブジェクトの分割代入を別に行う場合は、分割代入の式全体を()で囲ってないとSyntaxError: Unexpected token

let a, b;
{a, b} = { a: 10, b: 20 };
console.log(a, b);
// {a, b} = { a: 10, b: 20 }
//       ^
// SyntaxError: Unexpected token =

↓ 分割代入全体を()で囲う

let a, b;
({a, b} = { a: 10, b: 20 });
console.log(a, b); // 10 20

分割代入の前の文にセミコロン;が無いとエラーになる場合がある

変数宣言だけだとエラーにならない

let a, b
[a, b] = [1, 2]
console.log(a, b) // 1, 2

変数宣言時に値を代入しているとReferenceError: X is not defined

let a = 1, b = 2
[a, b] = [b, a]
console.log(a, b)
// [a, b] = [b, a]
//    ^
// ReferenceError: b is not defined

↓ 前の文にセミコロン;があればエラーにならない

let a = 1, b = 2;
[a, b] = [b, a]
console.log(a, b) // 2 1

分割代入の直前に文末にセミコロン;がないconsole.log()のような文があるとTypeError

let a = 1, b = 2
console.log(a, b)
[a, b] = [b, a]
console.log(a, b)
// [a, b] = [b, a]
//        ^
// TypeError: Cannot set property '2' of undefined

↓ 分割代入直前の文末にセミコロン;をつければOK

let a = 1, b = 2
console.log(a, b); // 1 2
[a, b] = [b, a]
console.log(a, b)  // 2 1

別に前の文の文末でなくても、分割代入式の直前にセミコロンがあればOKっぽい

let a = 1, b = 2
console.log(a, b) // 1 2
;
[a, b] = [b, a]
console.log(a, b)  // 2 1

分割代入式の前に;を書いてしまってもOK

let a = 1, b = 2
console.log(a, b) // 1 2
;[a, b] = [b, a]
console.log(a, b)  // 2 1

分割代入の直前がブロックとか、セミコロン;で文の終わりが明示されていればエラーにならないっぽい?

let a = 1, b = 2
{} // function func() {} とかでもOK
[a, b] = [b, a]
console.log(a, b) // 2 1
オブジェクトでも同様。分割代入式の直前が;かブロックでないとエラー
let cute, cool
({cute, cool} = { cute: '星宮いちご', cool: '音城セイラ' })
console.log(cute, cool) // 星宮いちご, 音城セイラ

変数宣言だけなら文末にセミコロン;がなくてもエラーにならないが、
変数宣言時に初期値の代入があるとエラー (TypeError)

let cute = '星宮いちご', cool = '霧矢あおい'
({cute, cool} = { cute: '大空あかり', cool: '氷上スミレ' })
// ({cute, cool} = { cute: '大空あかり', cool: '氷上スミレ' })
// ^
// TypeError: "霧矢あおい" is not a function

↓ 代入している文章が終わってなく、分割代入の式が続いていて関数だと判断されているので、分割代入式の前に;をつけるか、ブロックになる式が入ればOK

let cute = '星宮いちご', cool = '霧矢あおい';
({cute, cool} = { cute: '大空あかり', cool: '氷上スミレ' })
console.log(cute, cool) // 大空あかり 氷上スミレ

とか

let cute = '星宮いちご', cool = '霧矢あおい', n = 5
while(n--) { console.log(n) }
({cute, cool} = { cute: '大空あかり', cool: '氷上スミレ' })
console.log(cute, cool) // 大空あかり 氷上スミレ

ブロック式があるとか

var cute = '星宮いちご', cool = '霧矢あおい'
;({cute, cool} = { cute: '大空あかり', cool: '氷上スミレ' })
console.log(cute, cool) // 大空あかり 氷上スミレ

分割代入式の先頭を;で始めるとか

分割代入の前に入る文がブロックでない場合は文末にセミコロン;が無いとエラーになる (TypeError)

function myFunc() { console.log('OKOKOK-') }
var sexy = '神前美月', pop = '夏樹みくる'
myFunc()
({sexy, pop} = { sexy: '風沢そら', pop: '冴草きい' })
// ({sexy, pop} = { sexy: '風沢そら', pop: '冴草きい' })
// ^
// TypeError: myFunc(...) is not a function

↓ 分割代入の直前にセミコロン;があればOK

function myFunc() { console.log('OKOKOK-') }
var sexy = '神前美月', pop = '夏樹みくる'
myFunc();
({sexy, pop} = { sexy: '風沢そら', pop: '冴草きい' })
console.log(sexy, pop) // 風沢そら 冴草きい

 

まとめ

変数宣言と同時でない分割代入は、下記パターンで文章が続いていると判断されてエラーになるようです。

  • オブジェクトの場合は分割代入の式全体を()で囲ってないとエラーになる
  • 分割代入式の直前が「変数宣言のみ」又は、セミコロン;かブロック{}でないとエラーになる

 
最近のJSのコードやESLintで、JSでセミコロン;は不要になったみたいな印象を勝手に受けてたのですが、基本的に必要な文末にはセミコロン付けるようにした方が良いんじゃないかなって思いました。
変数宣言と同時でない所で使う分割代入式はセミコロン;から始めること。としても良いかもですが、この方がLintとかに怒られたりで設定とかが面倒そうです…


[参考]

PC持っての出張で便利だったアイテムを4つ

ここ数年田舎ちほー在住で月1ペースくらいで関東圏に行っていて仕事道具であるPC周りをバックパックに詰めて新幹線移動とゲストハウス滞在を繰り返していました。
その体験からPC持っての移動や宿泊時に便利だったものを4つ紹介したいと思います。(商品紹介記事ですね!!)

コンパクトなPCスタンド

f:id:kikiki-kiki:20181005141040j:plain

ラップトップの冷却のためとかスタンドは色々ありますが、移動で持ち運ぶとなるとコンパクトなものがジャスティスです。これは分割もできるのでPCケースとかに収納しておけるので良かったです。

f:id:kikiki-kiki:20181005141102j:plain 新幹線のようなテーブルが狭くコンセントが1つしかない場所だとPCに電源を繋いでUSBからスマートフォンやモバイルバッテリー充電をするのですが、テーブルの上がラップトップでいっぱいになりスマートフォンなどの置き場に困ります。このスタンドでラップトップを持ち上げると下にスペースができるので、そこにスマートフォンくらいなら置いておくことができます。

f:id:kikiki-kiki:20181005141148j:plain また、2つに分かれているので、どんなサイズのラップトップでもタブレットスマートフォンでも使用することができます。
難点は2つに別れているが故に、いい感じにポジショニングしないとPCがグラついてしまうので慣れるまで位置調整が少し大変なこと。小さく丸いので落として失くしてしまうリスクがあることです。(新幹線の中で落として転がっていって失くしかけました...)

類似品がいっぱいあってどれがオリジナルなのかちょっと判断つかないのですが機能的にはどれも同じようなものだと思います

ケーブルやUSBメモリーなどの小物を収納できるケース

f:id:kikiki-kiki:20181005140939j:plain
f:id:kikiki-kiki:20181005140946j:plain

カバンの中に充電器やケーブル・イヤフォンなどを入れておくと、行方不明になったりコード同士が絡まったりでストレスでした。
ゴム留めできるケースがあることを知り使ってみるとケースから出す/しまうの手間はかかりますが、行方不明やコードが絡まるというストレスからは開放されました!

私の場合はPCの充電器などよく使うものはPCケースに入れ、USBメモリーやカードリーダー、有線LANに繋いでwifi飛ばせる装置、SIMケース、モバイルバッテリーなど必要になるかもといったお小物類をまとめてケースに入れておき、ケースを持っていけば一応必要なものはあるという状態にして使っています。
どちらかと言えば移動中というよりホテルやワーキングスペースとかで必要になるようなものを中心に収納しています。
「使ったらしまう」を徹底してないと慌ててケースを持ってきたは良いけど肝心なものが入ってない!という事にもなるので、「使ったらケースにしまう」を習慣化しておくことが大事です。

類似品もサイズ違いもいっぱいあるので、マウスも入れたいとか、どう使うかを考えてサイズを選べば良いと思います。

インナーバック

f:id:kikiki-kiki:20181005135625j:plain
f:id:kikiki-kiki:20181005135633j:plain

タブレット、本、ノート、筆記用具、名刺、パスケースなど外側にもポケットが付いているので定位置を決めておきバックパックやカバンに入れておけば、移動中でもサッと必要なものを取り出せるので便利!コクヨのものはA4サイズの技術書やPCケースを使わなければ13インチのMacBookProも一緒に入れれるくらい収納力がありとても良かったです。
先の小物ケースに入れるには大きかったり、特に移動中とかに使いたくなるような物を中心に入れて使っています。

PCケース

f:id:kikiki-kiki:20181005135141j:plain

安いケースですが、それなりにクッション性もありケースの外側の収納に電源ケーブル・マウス・USB-C用のハブ・先に紹介したPCスタンドが余裕で入ります。
ダブルジップなのでバックパックに縦方向で入れておいてもチャックを開けてラップトップだけ取り出せるので、車内など狭い場所でもPC取り出しやすいので便利です。
落としたことがないので防御力がどの程度なのかは不明です。一応ちょっとした防滴にもなってるらしいですが、これも濡らしてみたことがないので性能面はわかりません。
難点としては持った時にジッパー側が下側になるのでジッパーが破損時にPCが落下してしまいそうという不安は多少あります。

こんな感じで、本や充電周りなど移動中に取り出したりするものはインナーバックかPCケースに収納し、宿泊先や出先のワークスペースで必要になりそうな細々したものは小物ケースに収納しておいて、お出かけの時はこのケースたちをバックパックに詰め込んで出張にでかけるというスタイルをやっていました。
今の所あまりストレスはありませんが、強いて言うなれば家で使う時に片付けをちゃんとしてないと、家の中で大捜索になってしまうことくらいでしょうか。ズボラなので…

ちなみに泊りがけの時にいつも使ってるバックパックは「CHUMS Sinawava 25」モリモリ入るし、ウェストポーチが合体してたり、ミニバックとか拡張性が高いし水が入りにくい設計にもなっているので気に入っています。

[チャムス] バックパック Sinawava 25 Brown

[チャムス] バックパック Sinawava 25 Brown

  • メディア: ウェア&シューズ