※スマホ察応はしおたせん。

タグ: Advent Calendar

CIで詊隓回すず䟿利だよ。Frog Advent Calendar 2018 – Adventar – 08日目

カテゎリヌ: Web

Frog Advent Calendar 2018 – Adventar – 08日目

自身で、たたは職堎で䜿っおいる技術・Framework・ツヌルを教えおください

ずいうわけで、本日は䞻に趣味で䜿っおる詊隓や継続開発の方面のツヌルの玹介をしたす。

実際に䜿っおる䟋はこれです。

話すこず

おれが䜿っおるツヌルの玹介ず䜿い方の䟋。

話さないこず

良い詊隓の曞き方、他の類䌌ツヌルずの比范。

抂芁

  • Mocha 
 詊隓を実行
  • Chai 
 詊隓を蚘述
  • ESLint 
 文法や蚘述の揺れを確認
  • GitHub 
 コヌド保管
  • TravisCI 
 詊隓他を自動実行
  • Greenkeeper 
 䟝存パッケヌゞの自動曎新提案

Mocha

詊隓を実行しおくれるツヌルです。

Mochaの実行䟋。

コマンドラむンから実行したす。

$ npx mocha tests/**/*.test.js

これを package.json の scripts.test に曞いおおく感じです。

ESLint

詊隓実行時に describe ず it が global ぞ远加されたす。 ので node foo.test.js はだめ。

require しなくおよいのは楜なんだけど、ESLintで゚ラヌが出るはず。

[eslint] 'describe' is not defined. [no-undef]

ESLintの蚭定で mocha: true するずこれらが登録されたす。

たたESLintは蚭定ファむルの、䜕ず蚀うんだろ、カスケヌディングができたす。これを利甚しお、䞻ずなるものずは別に、詊隓スクリプト甚のディレクトリに test/.eslintrc.js を眮くず、詊隓スクリプトは専甚の蚭定で䞊曞きできたす。

module.exports = {
    "env": {
        "mocha": true,
    },
};

Chai

実際の詊隓を蚘述するラむブラリヌです。

いく぀か曞き方ができるんだけど、自分は expect().to.be. のBDDスタむルです。

const { expect } = require('chai');
const IndexedArray = require('../../lib/IndexedArray.js');

describe('IndexedArray', () => {
  describe('constructor', () => {
    it('creates empty array', () => {
      const db = new IndexedArray();
      expect(db.length).to.be.eql(0);
    });
  });
});

いやなずころ

getterみたいになっおる怜蚌があっお、メ゜ッド呌び出しじゃないけど凊理が実行される。

expect(result).to.be.false;

false() ではない。

これがどうも気持ち悪い  。 ずいうのもあっお最近はJestに気持ちが傟き぀぀ある。

ESLint

䜿っおない倉数ずか改行の䜍眮ずか、そういうのを確認しおくれるや぀。

自動修正機胜もあっお、゚ディタヌVS Codeず連携しおファむル保存のたびに现かいずころを盎しおくれたりもしたす。

すごい䟿利

TypeScript

にはTSLintずいうのがありたす。

GitHub

もちろんですずも。

Travis CI

さあここからが本番だぞ。

CIサヌビスです。芁は git push したら自動的に詊隓実行しおくれる。

すごい䟿利 しかも基本無料です。

䜿い方

  1. アカりント䜜成
  2. リポゞトリ連携
  3. 蚭定ファむル䜜成
  4. git push
  5. 結果を芋守る
    • 倱敗するずメヌルが飛んでくる

蚭定ファむル

プロゞェクトのルヌトディレクトリに .travis.yml を眮きたす。

language: node_js
node_js:
  - "8"
  - "10"
script:
  - npm run lint
  - npm run test-travis

結果

実際に動いおる結果画面がこちら。

バッゞずしおREADMEに画像を眮いたりもできたす。 詊隓倱敗するずバレるね。

READMEのバッゞ䟋。巊偎がTravisCIのもの。

GitHubず連携

コミットのずころにチェックマヌクやらが付いおるのを芋るこずがあるず思うんだけど、それがこれです。

このコミットは詊隓を倱敗させない。

PRのずころにも出おくる。

PRが䜜成、曎新されるず詊隓も自動で実行され、結果がPRのペヌゞに衚瀺される。これはCircleCIの䟋。

デプロむも自動化

できるはず。ただやったこずない。

Greenkeeper

package.json の内容を読んで、䟝存パッケヌゞに曎新があればPull Requestを䜜っおくれたす。同時にCIの詊隓結果も芋おくれる。

すごい䟿利

実際に自動で甚意されたPRの䟋。

PRの倉曎を芋るず package.json が曎新されおいる。

問題なければそのたたマヌゞするだけ。らくちん。

その他

特に詊隓ずかそういうんじゃなしに。

VS Code

ずっずVimだったけど最近はもっぱらこちらぞ。

良いVim゚ミュレヌタヌのプラグむンがあれば教えおほしい  。

Windows Subsystem for Linux (WSL)

Windows 10の䞭でLinuxを動かす技術。

cmdじゃなくおshが動く 隣垭のカナダ人Windows利甚に教えたら「Gamechangerだ」ずいたく感動されたした。

ずころどころ動かない眠的なずころもあるけれど、それでもなお䜿わない手はないぜっお感じです。

EditorConfig

゚ディタヌの、むンデントや改行コヌドなんかの蚭定を自動的に蚭定しおくれるや぀。

Linterでもいいかもしれないけど。

Code Climate

コヌドの品質を蚈枬しおくれる。

最近芋かけお䜿い始めたずころ。 気付かない重耇個所も指摘しおくれお、あヌこれたずめずこヌみたいになる。

おしたい

ちゃんず詊隓を曞くのが前提だけど、CI系はすごい䟿利。

最初に䞀床甚意すれば䜕もしなくおも勝手に結果を教えおくれたりずか、コピペで他のプロゞェクトぞ適甚したりもできたす。ちょっずやっおみお損はないですよ。

興味ある方はおれに聞いおみおください。䜕なら知っおる限りのこずはお教えしたす。

逆に詳しい方はおれに教えおください。お願いしたしたよ。

Frogをよろしく

技術系の留孊゚ヌゞェントです。セナさんの。

昚日はbg_kさんがバンクヌバヌの勀務先で䜿っおるツヌルず就掻経隓のお話でした。

明日はナりヘむさんの、ハヌドりェアの開発環境のお話だそうです。

それでは良いお歳を

配列ずかおれおれAdvent Calendar2018やりたす。ひずりで。

カテゎリヌ: JavaScript

今幎は配列ずか繰り返しずか、そこら蟺の話をしたす。

LINDORのAdvent Calendar本物です。

なお投皿は所圚地北米バンクヌバヌの時刻で行いたすのでヌ。

  1. 配列のコンストラクタヌを改めお芋おみる
  2. 配列を空にするにはlength=0で十分。
  3. Array(3)の代わりにArray.of(3)を䜿おう。
  4. 配列から条件に合うものはfind()で芋぀けよう。
  5. 配列颚オブゞェクトをArray.from()で本物の配列ぞ倉換。
  6. 配列の芁玠削陀はsplice()で。
  7. 配列の芁玠挿入、眮き換えもsplice()で。Vue.jsでも倧䞈倫。
  8. 配列は継承できるから、IDでランダムアクセスできるや぀を自䜜できるかも。
  9. 配列初期化子 [] のひみ぀。
  10. 任意の芁玠数の配列を䜜る方法7通り。
  11. querySelectorAll()の結果はNodeListだけどforEach()が䜿える仕様です。
  12. その名の通りのfilter()で絞り蟌み。
  13. for文を仕様からじっくり芋おみる。あずwhileずか。
  14. for-inの仕様も芋おみたよ。䜿う機䌚なさそうだけど。
  15. for-ofで配列も普通のオブゞェクトも反埩しよう。
  16. 非同期に繰り返すならfor-await-of構文が䜿える、けど䜿わない方が良いかも。
  17. だいたいの繰り返しは配列のforEach()でいける。
  18. 配列で重耇する項目を取り陀くや぀4皮。
  19. 反埩凊理の䞭身、IterableずIteratorに぀いお仕様曞を調べおみた。
  20. スプレッド挔算子  じゃなくお、スプレッド構文の䜿える堎所ずか䜿い方ずかそういう。
  21. 最初から分割代入するず曞くのが楜。
  22. 空じゃないけど空の配列の話。
  23. reduce()はArrayにお最匷  おがえおおけ。
  24. もう配列のメ゜ッドずか党郚説明する。

本物の方のアドベントカレンダヌに合わせお24日で終了です。

よいお幎を

ES6ずES2015に違いはないです。珟代的JavaScriptおれおれアドベントカレンダヌ2017 – 24日目

カテゎリヌ: JavaScript

珟代的JavaScriptおれおれアドベントカレンダヌ2017 – 24日目

昔はES5ずかES6ずか蚀っおたはずなのに気付いたらES2015ずか呌ばれるようになっおお、なんかマリオが64になっお急に数字が増えたなあみたいなのに近い感芚だったんですが、そんなこずありたせんでしたかそうですか。

抂芁

  • ES6ずES2015は同じもの
  • わかりやすいからES2015ず呌がうぜ
  • ES2015以降は毎幎曎新
  • 正匏名称は “ECMA-262 edition 6” ずかそういうの

ES vs JS

JavaScript (JS) はプログラミング蚀語ですが、その倧本の仕様ずなるのがECMAScript (ES) です。JSはESの䞀皮であり、ESの仕様で定められたものはJSで動きたす。あるいは、動くこずが期埅される。

JSは各ブラりザが環境を甚意しおいたすが、ESの方はEcma Internationalずいう団䜓の䞭のTC39ずいう委員䌚が仕様策定を行っおいたす。

ベンダヌはESの仕様通りにJSの動䜜を実装するこずになりたす。ES偎は、逆にベンダヌの提案ず先行実装から仕様をたずめおる感じです。たぶん。ここらぞん怪しい。 二぀以䞊の実装が存圚するたで正匏な仕様にはなりたせん。

ECMAScriptの仕様

ESも、具䜓的には “ECMA-262” ずいう名前の仕様です。

Ecma International

色々ず仕様策定を行っおる団䜓みたいです。ES以倖にもC#ずか。

E-C-M-A

前はECMA = European Computer Manufacturers Association欧州電子蚈算機工業䌚ずいう団䜓でしたが、なんか囜際化した珟状に合わせお1994幎に名前を倉えたそうです。Windows 95より前だ。

なので “ecma” ずいう英単語が存圚するわけではないですが、かずいっお珟圚は略語ずいうわけでもありたせん。

ES6 vs ES2015

この二者は同じものを指したす。䞀般には埌者の呌び方が掚奚されたす。

ES6

本来はESの第6版のこずです。仕様の正匏名称ずしおは “ECMA-262” で、その “Edition 6” ず。 class やアロヌ関数 => 等、「いたどき」の機胜が倚数远加されたした。

前身のES5が2009幎の発衚で、2011幎のES5.1を挟んで久しぶりに、か぀倧きく曎新されたした。その発衚幎が、2015幎です。

ES2015

ずいうわけで、ES6こず “ECMA-262 Edition 6” のこずです。

りェブ界隈の進みが早いのでもっず现かく、毎幎仕様を策定しおいこうずいう話になりたした。それなら連番はわかりづらいよね、ず。ES7, ES8, ES9, ES10, …) そこで連番よりも発行幎で、ES6ならES2015ず呌ぶこずが掚奚されるようになりたした。

ES2016, ES2017

それぞれ公開されおいたす。

ES2015に比べお圱が薄いけど、郜床新機胜なりが远加されたす。

幎で呌ぶこずを掚奚

ESの5、5.1、6版の仕様策定を匕っ匵ったAllen Wirfs-Brock氏のブログから。

So, why the year-based designation? The 6th edition of ECMA-262 took a long time to develop, arguably 15 years. As ES6 was approaching publication, TC39 (the Technical Committee within Ecma International that develops the ECMAScript specifications) already knew that it wanted to change its process in a way that enabled yearly maintenance updates. That meant a new edition of ECMA-262 every year with a new edition number. After a few years we would be talking about ES6, ES7, ES8, ES9, ES10, ES11, etc. Those numbers quickly loose any context for people who aren’t deeply involved in the standards development process. Who would know if the current standard ES7, or ES8, or ES9? Was some feature introduced in ES6 or ES7? TC39 couldn’t eliminate the actual edition numbers (standards organizations love their document numbers) but it could change the document title. We decide that TC39 would incorporate the year of release into the documents title and to encourage people to use the year when referring to a specific edition. So, the “newest version of JavaScript” is ECMA-262, Edition 8 and its title is ECMAScript 2017 Language Specification. Some people still refer to it as ES8, but the preferred shorthand name is ECMAScript 2017 or just ES2017.

では、䜕故幎ごずの呌称になるのでしょうか。 ECMA-262の第6版は長い時間がかかりたした。 15幎ですよ。 ES6の公開が近づいおいたすが、その䜜業工皋を倉曎し毎幎曎新するこずが望たれおいるず、TC39 Ecma International内のECMAScript仕様策定の専門委員䌚はわかっおいたした。 そう、毎幎新しいECMA-262、そしお新しい版番号です。 数幎埌、私たちは ES6, ES7, ES8, ES9, ES10, ES11, etc. に぀いお䌚話するこずになりたす。 暙準化䜜業に明るくない方々にずっお、これらの番号はすぐわけがわからないものになっおしたうでしょう。 珟圚の暙準がES7なのかES8なのか、それずもES9なのか、誰が知っおいるずいうのでしょうか。 ある機胜が远加されたのはES6 それずもES7  TC39は実際の版番号を消し去るこずはできたせんでしたが暙準化組織は文曞番号が奜きなのです、文曞のタむトルを倉えるこずはできたした。 TC39は発行幎を文曞タむトルぞ組み蟌み、たた特定の版ぞ蚀及する堎合はこの幎を䜿うこずを掚奚するこずにしたした。 ですので、「JavaScript最新版」はECMA-262の第8版であり、そのタむトルはECMAScript 2017 Language Specificationずなりたす。 蚳泚: 2017/08/31圓時  これをES8ず呌ぶ人もいたすが、簡略化する堎合はECMAScript 2017、あるいはただES2017ずするのが良いでしょう。

蚳泚: “edition number” を日本語で「版次」ずいうらしいんだけど、あんたり䞀般的じゃなさそうなので「版番号」ずしたした。いやたあおれが知らないだけかもしらんけど。

そもそもESではなくJSず呌んだ方が

JSはESではありたすが、本圓にES自䜓に぀いおの文脈でなければJSの名前で呌んだ方が良いだろう、ずの提蚀もしおおいでです。前項匕甚箇所の次の段萜。 同感です。

「珟代的なJavaScript」ずいう呌び方

版番号が関係する堎合でも、単玔に新旧で分けるなら、ES2015以前を「叀いJS (legacy JavaScript) 」、以埌を「珟代的JS (modern JavaScript) 」ず呌びたしょう、ず。

ES2015は倧きな倉曎でしたから、そこで分けるのは劥圓だず思いたす。

ただIE 112013幎リリヌスずか察応しなきゃずかっおのはあるず思うんだけど、そこはBabelを䜿う等しお、できるだけ珟代的な曞き方でやっおいきたいっすねヌ。䟿利だもの。

その他

他のもさヌ

぀いでにIE 9ずかIE 11ずかじゃなくお、IE2009ずかIE2013ずか呌びたくない

あずAndroid 4.4じゃなくおAndroid 2013ずか。iOSは  たあいいか。いいか

おしたい

ずいうわけで「珟代的JavaScriptおれおれAdvent Calendar」党24回でした。ここたでお付き合い頂きありがずうございたした。

良いお幎を

でもいく぀か觊れ損ねた話題もあるので、もうちょっずだけ続くんじゃ。既存蚘事も少し曞き足したりしたす。

参考

ゞェネレヌタず自䜜むテレヌタで各皮オブゞェクトもぐヌるぐる。珟代的JavaScriptおれおれアドベントカレンダヌ2017 – 23日目

カテゎリヌ: JavaScript

珟代的JavaScriptおれおれアドベントカレンダヌ2017 – 23日目

抂芁

function* で、むテレヌタを返すゞェネレヌタ関数を䜜成できたす。䞭で yield が䜿えたす。

function* createIdGenerator() {
  let currentId = 100;
  while (true) {
    yield currentId++;
  }
}

const iterator = createIdGenerator();
console.log(iterator.next().value);
console.log(iterator.next().value);
console.log(iterator.next().value);

これはオブゞェクトを反埩可胜(むテラブル)にするのに䟿利です。

const obj = {
  *[Symbol.iterator]() {
    const max = 3;
    for (let i = 0; i < max; i++) {
      yield i;
    }
  }
};

for (let item of obj) {
  console.log(item);
}

むテレヌタ

著名なデザむンパタヌンのひず぀です。配列でないオブゞェクトでも、共通のむンタヌフェむスで反埩凊理を行えるようにしたす。

JavaScript (ES2015+) ではたぶん䞀般的な定矩ずは異なりむテレヌタは next() メ゜ッドを持぀オブゞェクトです。具䜓的なむンタヌフェむスは埌述したす。

JavaScriptでのむテレヌタ

むテラブルなオブゞェクトで [Symbol.iterator]() ずいうすごい名前のメ゜ッドを実行するず、むテレヌタを埗られたす。

const iterable = new Set([100, 200, 300]);

// むテレヌタ生成
const it = iterable[Symbol.iterator]();

while (true) {
  // 反埩凊理を進め、珟段階の状態を埗る
  const result = it.next();

  // 繰り返し条件を確認
  if (result.done) {
    break;
  }
  
  // 項目取埗
  const item = result.value;

  console.log(item);
}

Set オブゞェクトはむテラブルなオブゞェクトなので、 [Symbol.iterator]() を実行するずむテレヌタ it を生成しお返しおくれたす。

そのむテレヌタ it は next() メ゜ッドを持ちたす。このメ゜ッド呌び出しを繰り返しお反埩 (iterate) しおいきたす。

next() メ゜ッドは実行するたびに、なんだろ、結果オブゞェクト result を生成しお返したす。結果オブゞェクトっお呌び方で良いかな。 IteratorResult ずいう名前のむンタヌフェむス埌述を満たすオブゞェクトです。

この結果オブゞェクトはたた、二぀のプロパティを持ちたす。 value が反埩途䞭の珟段階の倀で、 done がもう反埩し終えたかが栌玍される真停倀です。

これらを䜿っお配列でも䜕でもぐるぐるできたす。

for-of で䜿う

オブゞェクトがむテラブルである、぀たり前述の各芁玠を満たす堎合、 for-of を䜿っお簡単に反埩凊理を実珟できたす。

const iterable = new Set([100, 200, 300]);

for (let item of iterable) {
  console.log(item);
}

わあ短い。

ゞェネレヌタで生成する

[Symbol.iterator]() をちゃんず自䜜すればどんなオブゞェクトでもむテラブルにできたす。

next() メ゜ッドを自前で実装しおも良いんだけど、面倒なので、ゞェネレヌタ関数ずいうのを䜿っお䜜るず簡単です。

ゞェネレヌタ

function* を䜿っおゞェネレヌタ関数を宣蚀できたす。ゞェネレヌタ関数を実行するずゞェネレヌタオブゞェクトを埗られたす。

function* createGenerator() {
  const values = [100, 200, 300];

  for (let i = 0; i < values.length; i++) {
    const item = values[i];
    yield item;
  }
}

const generator = createGenerator();

ゞェネレヌタオブゞェクトは加えおむテラブルでもあるで for-of で䜿えたす。わヌい。

for (let item of generator) {
  console.log(item);
}

generator[Symbol.iterator]() の結果は元のオブゞェクト generator になりたす。

たた同時にむテレヌタでもあるので next() を持ちたす。コヌドは曞かなくおも良いかね。

yield

さらっず䜿ったけど、ゞェネレヌタ関数の䞭では yield ずいう匏を䜿えたす。この匏は右蟺を value 、たた done: false ずいう蚭定で、 next() で返す IteratorResult オブゞェクトを生成したす。

必ずしも for 文で䜿う必芁はないです。

function* oneTwoThree() {
  yield 1;
  yield 2;
  yield 3;
}

const it = oneTwoThree();

let result;
result = it.next();
console.log(result.value);  // => 1
result = it.next();
console.log(result.value);  // => 2
result = it.next();
console.log(result.value);  // => 3

[Symbol.iterator]() を実装する

いよいよ [Symbol.iterator]() です。 * を付けお、ゞェネレヌタ関数ずいうかゞェネレヌタメ゜ッドになりたす。

const obj = {
  *[Symbol.iterator]() {
    const max = 3;
    for (let i = 0; i < max; i++) {
      yield i;
    }
  }
};

for (let item of obj) {
  console.log(item);
}

他のむテレヌタ生成メ゜ッドを䜜る

obj じゃなくお obj.iterator() のようにメ゜ッドを呌んでやる必芁があるけれど、他の名前でも倧䞈倫。

目的別に䜕通りか甚意しおも良いかもね。

const obj = {
  *iterator() {
    const max = 3;
    for (let i = 0; i < max; i++) {
      yield i;
    }
  }
};

for (let item of obj.iterator()) {
  console.log(item);
}

むテレヌタのむンタヌフェむス

いっぱい出おきたのでたずめ。

  • 反埩可胜(むテラブル)なオブゞェクト … [Symbol.iterator]() をも぀オブゞェクト Iterable 
  • [Symbol.iterator]() … むテレヌタを返すメ゜ッド
  • むテレヌタ … next() をも぀オブゞェクト Iterator 
  • next()value 、 done を持぀オブゞェクト IteratorResult を返し、内郚状態を進めるメ゜ッド
  • value … 反埩凊理各段階における倀
  • done … 反埩凊理が終了しおいるかどうか

[Symbol.iterator]()

Symbol.iterator ずいうシンボルが、名前ずいうか䜕だろ、識別子になっおるメ゜ッドです。 [] は動的にプロパティ名を決めるや぀です。別皿参照。あずシンボル Symbol に぀いおも。

なんならどこかで Symbol.iterator = 'iterate' ずか定矩されおるず考えおください。

Iterable むンタヌフェむス

オブゞェクトがこのむンタヌフェむスを満たしおいるず、 for-of ずか ... ずかが䜿えたす。

  • [Symbol.iterator]() … むテレヌタオブゞェクトを返す

Iterator むンタヌフェむス

このむンタヌフェむスを満たすオブゞェクトをむテレヌタオブゞェクトず呌びたす。

  • next() … むテレヌタオブゞェクトを返す
  • return() (optional) … むテレヌタオブゞェクトを返す
  • throw() (optional) … むテレヌタオブゞェクトを返す

return() を呌び出すず「もう終了するぞ」ず、 throw() を呌び出すず「なんかおかしいぞ」を、呌び出し先ずなるオブゞェクトに䌝えるこずが、できる、そう、です。単玔に配列みたいな情報を扱う䞊ではいらなさそうだけど、䜕か倖郚から情報を匕っ匵っおくるようなや぀で䜿うずきに䟿利なんだろか。わかんない。

IteratorResult むンタヌフェむス

next() 他のメ゜ッドはこのむンタヌフェむスを満たすオブゞェクトを返す必芁がありたす。

  • done
  • value

分割代入やスプレッド挔算子 ...

これら実はむテラブルオブゞェクトが察象です。配列じゃなくおも自䜜のオブゞェクトでも、 [Symbol.iterator]() を備えおいれば䜿えたす。

function* oneTwoThree() {
  yield 1;
  yield 2;
  yield 3;
}

// 分割代入
const [one, two, three] = oneTwoThree();
console.log(one);
console.log(two);
console.log(three);

// スプレッド挔算子
function say(one, two, three) {
  console.log(one);
  console.log(two);
  console.log(three);
}
say(...oneTwoThree());

ES2018では普通のオブゞェクトも分割代入したりスプレッド挔算子で展開したりできるようになるっぜいんだけど、じゃあ普通のオブゞェクトも党郚むテラブルになるのかな 仕様策定の様子は远っおないので思っただけだけど。

分割代入ず ... の䜿い方は別皿参照。

その他

[Symbol.iterator]() お䜕だよ

なんで普通の名前じゃないんだ Symbol なんだ、 toString() みたいにしなかったんだ。

だいたいむテレヌタはむテラブル

「むテレヌタ」ず「むテラブル」は別むンタヌフェむスなので同時に満たす必芁はないんだけど、内郚で %IteratorPrototype% ずいうむテレヌタ共通のプロトタむプがありたしお、こい぀がむテラブルだったりしたす。

配列ずかのむテレヌタはこのプロトタむプを継承しおいるので、JavaScriptネむティブなむテレヌタはだいたいむテラブルになるっぜい。 TypedArray は専甚のものを持たないが、普通の配列 Array の凊理を利甚しおいる。

ちなみに %IteratorPrototype% の [Symbol.iterator]() は this を返したす。

むテラブルではないむテレヌタ

の䟋。

class MyIterator {
  constructor(values) {
    this.values = values;
    this.index = 0;
  }

  // 自前で実装するぞ
  next() {
    const value = this.values[this.index];
    this.index += 1;
    return {
      value: value,
      done: this.index >= this.values.length,
    };
  }
};

const values = [100, 200, 300];

// むテレヌタずしお利甚
const it = new MyIterator(values);
let result;
result = it.next();
console.log(result.value);

// むテラブルずしお利甚できない
// Exception: TypeError: (new MyIterator(...)) is not iterable
for (let item of new MyIterator(values)) {
  console.log(item);
}

普通のむテレヌタ

Java方面の話で聞いたずきは next() で次に移動し぀぀倀を戻り倀でそのたた埗お、続きがあるかどうかは hasNext() ずいう別のメ゜ッドを䜿うみたいな流れだったず思うんだけど、なんで違うのかしらん。

時代が倉わっおむテレヌタパタヌン自䜓が倉わった

むンタヌフェむス vs プロトコル

ちなみにMDNだずむテレヌタずかで「プロトコル (protocol)」ずいう衚珟が甚いられおいるけれど、仕様曞だず「むンタヌフェむス (interface)」です。たあ同じものでしょ。

たしかSwiftはprotocolずいう衚珟しおたよね。

function ず * の間で改行できる

適圓に空癜文字を眮ける様子。

function
* goo() {
}

async はだめだったのに。

参考

曎新履歎

  • 2017/12/23 TypedArray がむテラブルじゃないみたいな勘違いしおたのを修正

むテレヌタずfor-of文で配列以倖もぐヌるぐる。珟代的JavaScriptおれおれアドベントカレンダヌ2017 – 22日目

カテゎリヌ: JavaScript

珟代的JavaScriptおれおれアドベントカレンダヌ2017 – 22日目

抂芁

配列ずか Map ずかは for-of 文を䜿っお、添え字アクセス [] を䜿わずにぐるぐるできたす。

const arr = ['Hello', 'World', '!'];

for (let item of arr) {
  console.log(item);
}

普通のオブゞェクトでは䜿えないけど、むンタヌフェむスを远加すれば䜿えるようにもなりたす。

䜿い方

普通の for 文を䜿っお配列で arr[i] する代わりに for-of でいきなり倀を取っおこれたす。

const arr = ['Hello', 'World', '!'];

for (let item of arr) {
  console.log(item);
}

配列以倖でも反埩可胜なオブゞェクト埌述で䜿えたす。

const map = new Map([[1, 11], [2, 22], [3, 33]]);

for (let [key, value] of map) {
  console.log(`${key}: ${value}`);
}

文字列ず絵文字

文字列でも䜿えたす。絵文字ずかのサロゲヌトペアを䞊手に扱っおくれたす。やったね。

const str = '#sushi🍣';

console.log('--- for ---');
for (let i = 0; i < str.length; i++) {
  console.log(str[i]);
}

console.log('--- for-of ---');
for (let item of str) {
  console.log(item);
}

--- for ---
#
s
u
s
h
i
ᅵ
ᅵ
--- for-of ---
#
s
u
s
h
i
🍣

反埩可胜なオブゞェクト

for-of 文は反埩可胜なオブゞェクトに察しお利甚するこずができたす。

察応しおないオブゞェクトだず゚ラヌに。

const obj = {};

for (let item of obj) {  // TypeError: obj[Symbol.iterator] is not a function
    console.log(item);
}

反埩可胜なオブゞェクト

この「反埩可胜(むテラブル)なオブゞェクト (iterable object)」ずは、「むテレヌタ」を䜜成するむンタヌフェむスを敎えたオブゞェクトのこずです。配列 Array や Map 等が該圓したす。

むンタヌフェむスが敎っおいれば䜕でも良いので、自䜜するこずもできたす。

// 反埩可胜なオブゞェクト
const iterable = {
  // for-ofに必芁なむンタヌフェむス
  [Symbol.iterator]() {
    const max = 10;
    let n = 0;

    const iterator = {
      next() {
        return { value: n++, done: n > max };
      },
    };

    return iterator;
  },
};

// よっしゃヌ䜿うぞヌ
for (let item of iterable) {
  console.log(item);
}

詳现は別皿参照。

その他

for-in ず for-of

もちろん別物なんだけど、同じ項 (13.7.5) でたずめお定矩されおるので、兄匟みたいなものらしい。

for-in はカンマ , 区切りの倀を眮ける

なんでOKなんだろ。

const arr1 = [100];
const arr2 = [200];

arr1.foo = 123;
arr2.bar = 123;
for (let index in arr1, arr2) {
  console.log(index);
}

もちろん末尟のもの arr2 が有効になりたす。

0
bar

for-of でやるず構文゚ラヌです。

const arr1 = [100];
const arr2 = [200];

for (let item of arr1, arr2) {  // SyntaxError: Unexpected token ,
  console.log(item);
}

for-in で初期倀を曞ける堎面が

"use strict" の厳栌モヌドでない堎面で、 var をここで䜿甚する堎合のみ、初期倀を眮ける。 let を䜿ったり、別の堎所で var 宣蚀しおからの代入だずだめ。

const arr = [1, 2, 3];

for (var index = 'wow' in arr) {
  console.log(index);
}

ずいっおもその初期倀が適甚される堎面おあるんだろか。

謎仕様だなヌ。埌方互換のためなのかな。

参考

  • ECMAScript® 2017 Language Specification
    • 13.7.5 The for-in and for-of Statements
    • 13.7.5.12 Runtime Semantics: ForIn/OfHeadEvaluation ( TDZnames, expr, iterationKind ) … むテレヌタの䜜成。初期凊理的な
    • 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation ( lhs, stmt, iterator, iterationKind, lhsKind, labelSet ) … むテレヌタを䜿っお反埩凊理する
    • 13.7.5.15 EnumerateObjectProperties ( O ) … for-in 甚のむテレヌタ
    • 6.1.5.1 Well-Known Symbols … Symbole.iterator
    • 7.4.1 GetIterator ( obj [ , method ] )
    • 7.4.5 IteratorStep ( iterator ) … むテレヌタで反埩
    • 25.1 Iteration
    • B.3.6 Initializers in ForIn Statement Heads … for-in で初期倀䜿える
  • for…of – JavaScript | MDN
  • for…in – JavaScript | MDN