<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="http://organizeseries.com/"
	>

<channel>
	<title>ECMAScript &#8211; HTML5Experts.jp</title>
	<atom:link href="/tag/ecmascript/feed/" rel="self" type="application/rss+xml" />
	<link>https://html5experts.jp</link>
	<description>日本に、もっとエキスパートを。</description>
	<lastBuildDate>Sat, 07 Jul 2018 03:14:05 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.19</generator>
	<item>
		<title>Node.jsでSlack Command Botをつくってみよう</title>
		<link>/girlie_mac/22535/</link>
		<pubDate>Fri, 03 Mar 2017 00:00:22 +0000</pubDate>
		<dc:creator><![CDATA[Tomomi Imura]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[ES6]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Slack]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[bot]]></category>
		<category><![CDATA[海外]]></category>

		<guid isPermaLink="false">/?p=22535</guid>
		<description><![CDATA[こんにちは。ごぶさたしています。以前の執筆から１年ちょっとになるのですが、その当時はInternet of Things(IoT)について書いたのですが、最近では市場がある程度まで到達したからでしょうか、それとも脆弱性の...]]></description>
				<content:encoded><![CDATA[<p>こんにちは。ごぶさたしています。以前の執筆から１年ちょっとになるのですが、その当時はInternet of Things(IoT)について書いたのですが、最近では市場がある程度まで到達したからでしょうか、それとも脆弱性の問題を問われることが多くなったせいでしょうか、話題は少し落ち着いてきたかに思われます。さて今ホットな話題は何でしょうか、ということで今回はChat Botsについて書いてみようと思います。</p>

<h3>E-Commerceから Conversational Commerceへ</h3>

<p>ここ最近話題になることが多いAIやBotsですが、私の周りではConversational interface、Conversational UXなどという言葉が去年からたびたび使われるようになっているようです。</p>

<p>これはAmazon Alexaなどのデバイスや、Facebook Messengerなどチャットアプリケーションなどの対話型テクノロジーをいかに活用しその使い勝手をよくするか、ということなのですが、必ずしもアプリケーションのUIデザインそのものを述べているわけではなく、既存のサービスを延長することを指していることも多いでしょう。例えば、今まではモバイル上のアプリケーションのみで車を呼べていたUberが、<a href="https://newsroom.uber.com/messengerlaunch/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Facebook Messenger のチャットからも車をを呼べるような機能</a>を加えたり、Slack上でTaco Bellからタコスをオーダーできる<a href="https://www.tacobell.com/feed/tacobot" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TacoBot</a>、というのもが挙げられます。</p>

<h3>Slack Botを書いてみよう</h3>

<p>さて、というわけで何かBotを書いてみたいと思いませんか？ここはNode.jsでSlack botを作成する方法を紹介したいと思います。</p>

<p>このチュートリアルでは、ディベロッパー向けのHTTPステータスコードのルックアップができるスラッシュ・コマンドを作ってみます。ここでは私が５年ほど前に何気なく作って、Mashableなどで紹介され思わぬ反響を得てしまった<a href="http://http.cat/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTTP Status Cats</a>を使ってみます。具体的には、Slack上でユーザが、<code>/httpstatus [code]</code> （例えば <code>/httpstatus 404</code>）と入力すると、そのステータスコードの意味と猫が一緒に表示される、という簡単なbotです。</p>

<p>まず試してみたい方は、<a href="http://www.girliemac.com/slack-httpstatuscats/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTTP Status Cats command for Slack</a>を自分がアドミン権限のあるのチャットチームにインストールしてみてください。</p>

<p><img src="/wp-content/uploads/2017/02/slack-httpstatuscats.gif" alt="slack-httpstatuscats gif animation" width="640" height="437" class="aligncenter size-full wp-image-22558" /></p>

<p>さて、このチュートリアルは２つのパートに分けられます。</p>

<ol>
<li>スラッシュ・コマンドを書いて、自分のSlackチームにインストールする
<li>OAuthを使ってボットを<a href="https://slack.com/apps" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Slack&#8217;s App Directory</a>などで誰もがインストールできるようにする</ol>

<p></ol></p>

<p>とりあえず動くbotを書いてみたい、と思う方は１だけ試してみてで十分ですが、botをみんなにシェアしたい方は２も読んでみてください。</p>

<p><a href="https://github.com/girliemac/slack-httpstatuscats" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ソースコード</a>と実際のボットのインストールボタンは両方GitHubにあります。では始めましょう！</p>

<h2>1 プライベートなスラッシュコマンドボットの作成</h2>

<p>ここで作るのは、Slackの公式な用語でいうところの<a href="https://api.slack.com/custom-integrations" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Custom Integrations</a>というもので、自分のチャットグループ専用のプライベートなbot、もしくはいわゆるAppとして発表する前にドライ・ランを行うことを指します。アカウントを持っていない方はまずサインアップしてから始めましょう。</p>

<h3>1.1 スラッシュコマンドの設定</h3>

<p>ログインして、<a href="https://my.slack.com/services/new/slash-commands" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">my.slack.com/services/new/slash-commands</a>でコマンドを選びます。ここでは<code>/httpstatus</code>と入力し<strong>Add Slash Command Integration</strong>ボタンをクリックして次のステップへ進みます。</p>

<p>Tokenなどの欄がありますが現時点では、(1) Command、 (2) URL、 (3) Method、の３つが必要になります。</p>

<p><img src="/wp-content/uploads/2017/02/slack-config-custom-integration.png" alt="slack-config-custom-integration" width="431" height="640" class="aligncenter size-full wp-image-22561" srcset="/wp-content/uploads/2017/02/slack-config-custom-integration.png 431w, /wp-content/uploads/2017/02/slack-config-custom-integration-202x300.png 202w, /wp-content/uploads/2017/02/slack-config-custom-integration-139x207.png 139w" sizes="(max-width: 431px) 100vw, 431px" /></p>

<p>(1)には、<code>/httpstatus</code>、(3)には、<code>POST</code>、そして(2)のURLは次のように設定してください。</p>

<p>開発中に使用するURLを取得するには<a href="https://ngrok.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ngrok</a>を使ってみましょう。いろいろなツールがあるのですが、これは自分のローカルホストをパブリックURLとしてトンネルできるというとても便利なツールなので私のイチオシです。開発途中にデプロイすることなく、Webhookが手軽に使えます。自分のローカルホスト、たとえば  <code>http://localhost:3000/</code> をつかったままOAuthのテストもできるのです。（注：よく聞かれるのですが、ngrokはあくまでも開発ツールですのでプロダクションには適していません。デプロイメントに関しては最後の章を読んでください）</p>

<p><a href="https://ngrok.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://ngrok.com/</a>から自分のマシンにngrokをインストールしたら、ターミナルで自分の使いたいポート番号（このチュートリアルでは 3000）を設定します。</p>

<p></p><pre class="crayon-plain-tag">$ ngrok http 3000</pre><p></p>

<p>すると下のスクリーンショットのように、Forwardingアドレスが取得できるので、そのURL（例えば<a href="https://71f03962.ngrok.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://71f03962.ngrok.io/</a>)をSlackセッティングの、上のスクリーンショットで示された(2)の欄で使います。</p>

<p><img src="/wp-content/uploads/2017/02/ngrok.png" alt="ngrok" width="640" height="349" class="aligncenter size-full wp-image-22538" srcset="/wp-content/uploads/2017/02/ngrok.png 640w, /wp-content/uploads/2017/02/ngrok-300x164.png 300w, /wp-content/uploads/2017/02/ngrok-207x113.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>すべての設定が終えたらSaveボタンを押します。&#8221;Your settings have been saved!&#8221;のメッセージが画面上部に現れるのを確認してください。</p>

<h3>1.2 Node.js を使ってレスポンスを書く</h3>

<p>基本的にbotは、ユーザがSlackインターフェイス上でコマンドを実行した際HTTP POST（または設定次第では GET)によって指定先のURLにメッセージが届け、プログラムでその応答をユーザに返す、という作業になります。</p>

<p>たとえばそのユーザが<code>/httpstatus 302</code>というコマンドを送信した場合、指定URLに送られるデータは次のようになります。</p>

<p></p><pre class="crayon-plain-tag">command=/httpstatus
text=302
response_url=https://hooks.slack.com/commands/1234/5678
…</pre><p></p>

<p>Botは、これに対する応答をユーザに返します。この場合はユーザが尋ねているステータス302の定義と<a href="https://http.cat/302" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">この猫</a>を返しましょう。</p>

<p>ではそのコードを書いてみましょう。</p>

<p>まず、<strong>Express.js</strong>と<strong>body-parser</strong>をインストールします。</p>

<p></p><pre class="crayon-plain-tag">$ npm install express body-parser --save</pre><p></p>

<p><strong>index.js</strong>で、<code>express</code>のインスタンスを作り、先ほどngrokで設定したポート番号、3000でサーバを始動します。</p>

<p></p><pre class="crayon-plain-tag">'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

const server = app.listen(3000, () =&gt; { 
console.log('Express server listening on port %d in %s mode', server.address().port, app.settings.env);});</pre><p></p>

<p>次はHTTP POSTルートメソッドで、コマンドを扱います。</p>

<p></p><pre class="crayon-plain-tag">app.post('/', (req, res) =&gt; {
 let text = req.body.text;
 // ここでbotを書きます
});</pre><p></p>

<p>ここで<code>text</code>の値を取得します。HTTP Status botの場合、<code>/httpstatus</code> コマンドの値、例えば&#8221;404&#8243;が <code>text</code>の値になります。同時に、ユーザが数字以外を入力した際にエラーメッセージを送るなどのエラーチェックもしておきましょう。</p>

<p></p><pre class="crayon-plain-tag">if(! /^\d+$/.test(q.text)) { // not a digit
 res.send('Error: enter a valid status code, such as 200');   
 return;
}</pre><p></p>

<p>このエラーは、ユーザだけにプライベートに送信されるメッセージでチャットそのものには表示されません。</p>

<p>エラーがない場合は、コマンドに対する応答をJSONとしてレスポンスします。</p>

<p></p><pre class="crayon-plain-tag">let data = {
 response_type: 'in_channel', 
 text: '302: Found',
 attachments:[{
   image_url: 'https://http.cat/302.jpg'
 }]
};
res.json(data);</pre><p></p>

<p><code>response_type</code>を<code>in_channel</code>とすることで応答はチャットメンバー全員に見えるように送信されます。デフォルトはその逆の<code>ephemeral</code>で、コマンドを送ったユーザのみに表示されます。</p>

<p>このコマンドと応答は次のようになります。</p>

<p><img src="/wp-content/uploads/2017/02/slack-command.png" alt="slack-command" width="640" height="491" class="aligncenter size-full wp-image-22540" srcset="/wp-content/uploads/2017/02/slack-command.png 640w, /wp-content/uploads/2017/02/slack-command-300x230.png 300w, /wp-content/uploads/2017/02/slack-command-207x159.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>このサンプルコードでは、応答をわかりやすくハードコードで示してありますが、実際はストリングなどは別のファイルに定義しています。下のスクリーンショットのように存在しないHTTPステータスに対してのエラーメッセージも定義しましょう。実際のコードは<a href="https://github.com/girliemac/slack-httpstatuscats" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ソースコード</a>を参照してください。</p>

<p><img src="/wp-content/uploads/2017/02/slack-command-private.png" alt="slack-command-private" width="640" height="60" class="aligncenter size-full wp-image-22539" srcset="/wp-content/uploads/2017/02/slack-command-private.png 640w, /wp-content/uploads/2017/02/slack-command-private-300x28.png 300w, /wp-content/uploads/2017/02/slack-command-private-207x19.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>ディスプレイはボーダー色などのカスタマイズが可能です。詳しくはSlackドキュメンテーションの<a href="https://api.slack.com/docs/message-formatting" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Basic message formatting</a>を参照してください。</p>

<p>次のステップでは、このボットを自分のチャットグループ以外に配布するために必要な認証とコードのデプロイについてです。</p>

<h2>2. Slack Botのディストリビューション</h2>

<p>この「Custom Integration」をインストール可能な「App」にするには、コードのデプロイをして他のチャットにもインストールできるようにせねばならないのですが、そのためにはあといつくかのステップが必要になります。</p>

<h3>2.1 Appセットアップ</h3>

<p>まず、自分のAppを申請し、クライアントIDやシークレットなどのクレデンシャルを取得します。<a href="https://api.slack.com/apps" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://api.slack.com/apps</a>で<strong>Create an App</strong>ボタンをクリックしてください。</p>

<p><img src="/wp-content/uploads/2017/02/slack-create-app.png" alt="slack-create-app" width="614" height="640" class="aligncenter size-full wp-image-22542" srcset="/wp-content/uploads/2017/02/slack-create-app.png 614w, /wp-content/uploads/2017/02/slack-create-app-288x300.png 288w, /wp-content/uploads/2017/02/slack-create-app-199x207.png 199w" sizes="(max-width: 614px) 100vw, 614px" /></p>

<p>このフォームにはいくつもの欄があり少しわかりづらいのですが、スラッシュコマンドのbotには次の3つが最低必要になります。</p>

<ul>
<li><strong>Basic Information</strong> (at <a href="https://api.slack.com/apps/YOUR_APP_ID/general%29" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://api.slack.com/apps/YOUR_APP_ID/general)</a></li>
<li><strong>OAuth &amp; Permissions</strong> (at …/YOUR_APP_ID/oauth)</li>
<li><strong>Slash Commands</strong> (at …/YOUR_APP_ID/slash-commands)</li>
</ul>

<h3>2.1.1 API Keyを.envファイルに保管</h3>

<p>ここで取得した<code>Client ID</code>、<code>Client secret</code>、<code>Verification token</code>は <strong>.env</strong> ファイルに別に保管してbotのメインのコードから切り離すことを推奨します。gitを使う場合は、このファイルを <strong>.gitignore</strong> ファイルに付け加えるのを忘れずに。</p>

<p></p><pre class="crayon-plain-tag">SLACK_CLIENT_ID=12345XXXXX.09876XXXXX 
SLACK_CLIENT_SECRET=535d2f9....
SLACK_VERIFICATION_TOKEN=42P829U...</pre><p></p>

<h3>2.1.2 Foremanを使う</h3>

<p>他にも手段はありますが、<a href="https://heroku.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Heroku</a>にデプロイするために私は<a href="http://strongloop.github.io/node-foreman/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Node Foreman</a>を使っています。Foremanを使うには、npmを使ってglobalフラッグでインストールしてください。</p>

<p></p><pre class="crayon-plain-tag">$ npm install -g foreman</pre><p></p>

<p>アプリケーションの Root に <code>.procfile</code> を作成し、この一行を加えます。</p>

<p></p><pre class="crayon-plain-tag">web: node index.js</pre><p></p>

<p>index.jsを実行するには <code>node index.js</code>の代わりに次のコマンドを使います。</p>

<p></p><pre class="crayon-plain-tag">$ nf start</pre><p></p>

<h2>2.2 ユーザの認証</h2>

<p>Slackは認証には<a href="https://oauth.net/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">OAuth</a>を使っています。実際には自分でOAuthを実装しなくても、<a href="https://api.slack.com/docs/slack-button" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Slack ボタン</a>を使えば簡単に認証できるようになっています。</p>

<p>公式のドキュメンテーションのダイアグラムに手を加えて、流れをわかりやすくするためにGIFアニメーションにしてみました。</p>

<p><img src="/wp-content/uploads/2017/02/slack-oauth-1.gif" alt="slack-oauth gif animation" width="640" height="387" class="aligncenter size-full wp-image-22559" /></p>

<p>ここでの実際のフローは次のようになります。</p>

<ol>
<li>ウェブページを作成し、認証ボタンを置く。ユーザがボタンをクリックするとパラメータがSlackに送信される(ユーザは認証ページにリダイレクトされる)。
<li>Node appには、SlackからGETで10分だけ有効な仮のコードが送られる。
<li>アクセストークンを得るために <a href="https://api.slack.com/methods/oauth.access" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">oauth.access</a> API使い認証コードをPOSTする。Node app側から`200 OK`を受け取り次第、このプロセスが完了。
<li>オプションとして、このトークンを使ってSlackの他のAPIにもアクセス。例えば、認証後、ユーザをhttps://team-name.slack.comにリダイレクトするなど。/
</ol>

<h3>2.2.1 Slack ボタンの設定</h3>

<p>Slackボタンを使うには、まずウェブページを作成してください。私の場合はこのNode Appとは切り離した別のHTMLページを作成し、<a href="http://www.girliemac.com/slack-httpstatuscats/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">GitHub Pages</a>にホストしました。</p>

<p>次にボタンを設定しましょう。 <a href="https://api.slack.com/docs/slack-button" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://api.slack.com/docs/slack-button</a> に行き、<strong>Add the Slack button</strong> までスクロールして下さい。</p>

<p><img src="/wp-content/uploads/2017/02/slack-generate-button.png" alt="slack-generate-button" width="640" height="268" class="aligncenter size-full wp-image-22543" srcset="/wp-content/uploads/2017/02/slack-generate-button.png 640w, /wp-content/uploads/2017/02/slack-generate-button-300x126.png 300w, /wp-content/uploads/2017/02/slack-generate-button-207x87.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>このボタン作成ツールの<strong>Commends</strong>のチェックボックスをチェックします。</p>

<p>上で示したフローの４を実行したい場合は、このGETパラメータを下のように変更します。</p>

<p></p><pre class="crayon-plain-tag">&lt;a href="https://slack.com/oauth/authorize?scope=commands+team%3Aread&amp;client_id=your_client_id"&gt;</pre><p></p>

<p>ここで<code>scope</code>に着目してみてください。<code>commands</code>の他に<code>team:read</code>(コロンは<strong>%3A</strong>とエスケープ)が必要になります。詳しくは<a href="https://api.slack.com/docs/oauth-scopes" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">OAuth scopes on the Slack API docs</a>で。</p>

<p><img src="/wp-content/uploads/2017/02/slack-button.png" alt="slack-button" width="139" height="40" class="aligncenter size-full wp-image-22548" /></p>

<h3>2.2.2 トークンの発行</h3>

<p>さて、Nodeコードに戻りましょう。仮のコード(<code>req.query.code</code>)をGETで取得するためにまたExpress.jsを使います。</p>

<p>何でもよいのですがここでは<code>/slack</code> routeを使いましょう。この場合ngrokのURL は <code>http://71f03962.ngrok.io/slack</code> のようになります。Slack App設定ページ（https://api.slack.com/apps/YOUR_APP_ID/oauth）の、<strong>OAuth &amp; Permissions</strong> セクションにある、<em>Redirect URL</em>の欄にはこのURLを設定してください。</p>

<p>仮の<code>code</code>を取得されたら、それを自分のAPIクレデンシャルとともにPOSTで送って、トークンと交換します。POSTするためにここではNode.jsのHTTPリクエストクライアントである、<code>Request</code>を使いましょう。</p>

<p></p><pre class="crayon-plain-tag">$ npm install request --save</pre><p></p>

<p>仮の<code>code</code>を取得し、それを<code>token</code>と交換するコードが下になります。</p>

<p></p><pre class="crayon-plain-tag">const request = require('request');

app.get('/slack', function(req, res){
 let data = {form: {
   client_id: process.env.SLACK_CLIENT_ID,
   client_secret: process.env.SLACK_CLIENT_SECRET,
   code: req.query.code
 }};

 request.post('https://slack.com/api/oauth.access', data, function (error, response, body) {
   if (!error &amp;&amp; response.statusCode == 200) {
     // おしまい！
     // ここからはオプションでチーム情報を取得
     let token = JSON.parse(body).access_token; // Auth token
   } ...</pre><p></p>

<h3>2.2.3 オプショナル： ユーザをチームURLにダイレクトする</h3>

<p>認証が済んだらそこで終えてもよいのですが、この画面でユーザを置き去りにするのはあまりよいUXとはいえないので、チームページにリダイレクトしてみましょう。</p>

<p>リダイレクトURLのサブドメインとなるチーム名は<a href="https://api.slack.com/methods/team.info" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">team.info</a>APIで取得できます。</p>

<p>このAPIを使うにはトークンが必要なので前述のコードでの、トークンにアクセスする箇所に下のコードを追加します。</p>

<p></p><pre class="crayon-plain-tag">...
request.post('https://slack.com/api/team.info', {form: {token: token}}, function (error, response, body) {
 if (!error &amp;&amp; response.statusCode == 200) {
   let team = JSON.parse(body).team.domain;
   res.redirect('http://' +team+ '.slack.com');
 }
});</pre><p></p>

<p>これで API からチーム名(<code>team.domain</code>)が返されました。最終的にこれを使ってチームURLにリダイレクトしてできあがり！</p>

<p>このチュートリアルでは簡素化したコードを使いましたが、<a href="https://github.com/girliemac/slack-httpstatuscats" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">全ソースコードはGitHubで</a>見てみてください。</p>

<h2>2.3 サーバにデプロイする</h2>

<p>最後にデプロイしておしまいです。APIクレデンシャルの<strong>env vars</strong>設定を忘れないように！私はHerokuを使っているのですが、Herokuの場合、<code>heroku config</code>コマンドを使います。例えば、<code>heroku config:set API_KEY=123456</code>というふうに設定してください。</p>

<p>Slackの設定で画面で指定したngrok URLを、デプロイ先のURLに変更するのもお忘れなく。</p>

<p>さて、プロセスが少し面倒ですが、コード自体は簡単だったと思います。もし何か面白いボットを作った際にはぜひ教えてくださいね！</p>

<p><img src="/wp-content/uploads/2017/02/slack-worked.png" alt="slack-worked" width="200" height="200" class="aligncenter size-full wp-image-22546" srcset="/wp-content/uploads/2017/02/slack-worked.png 200w, /wp-content/uploads/2017/02/slack-worked-150x150.png 150w" sizes="(max-width: 200px) 100vw, 200px" /></p>
]]></content:encoded>
			</item>
		<item>
		<title>テンプレートエンジン不要？JavaScriptで文字列処理を簡潔にするTemplate literal</title>
		<link>/takazudo/17396/</link>
		<pubDate>Mon, 19 Oct 2015 00:00:58 +0000</pubDate>
		<dc:creator><![CDATA[高津戸壮]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">/?p=17396</guid>
		<description><![CDATA[連載： ECMAScript 2015（ECMAScript 6）特集 (7)これまでのJavaScriptでは、複雑な文字列処理はテンプレートエンジンを使うことが一般的でした。しかしECMAScript 2015（EC...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/ecma2015/" class="series-336" title="ECMAScript 2015（ECMAScript 6）特集" data-wpel-link="internal">ECMAScript 2015（ECMAScript 6）特集</a> (7)</div><p>これまでのJavaScriptでは、複雑な文字列処理はテンプレートエンジンを使うことが一般的でした。しかしECMAScript 2015（ECMAScript 6）では、パワフルなTemplate literalが標準で利用できるようになりました。この新たに追加されたTemplate literalについて、概要とサンプルコードを紹介します。
<img src="/wp-content/uploads/2015/10/Ecma_RVB-003.jpg" alt="" width="373" height="146" class="aligncenter size-full wp-image-17453" srcset="/wp-content/uploads/2015/10/Ecma_RVB-003.jpg 373w, /wp-content/uploads/2015/10/Ecma_RVB-003-300x117.jpg 300w, /wp-content/uploads/2015/10/Ecma_RVB-003-207x81.jpg 207w" sizes="(max-width: 373px) 100vw, 373px" /></p>

<h2>これまでの文字列組み立て</h2>

<p>ES6で追加されたTemplate literalを使うと、文字列をより柔軟に、シンプルに組み立てることができます。例えば、これまでのJavaScriptでは、文字列を組み立てるために、例えば以下のような方法を取る必要がありました。</p>

<p></p><pre class="crayon-plain-tag">var name = 'john';
var country = 'japan';

var str1 = 'Hello! My name is ' + name + '. I live in ' + country + '.';

var str2 = [
  'Hello! My name is ',
  name,
  '. I live in ',
  country,
  '.'
].join('');

console.log(str1); // "Hello! My name is john. I live in japan."
console.log(str2); // "Hello! My name is john. I live in japan."</pre><p></p>

<p>文字列の断片を複数作り、<code>+</code>や<code>concat</code>でつなぎ合わせたり、配列に突っ込んで<code>join</code>したりなどといった方法です。単純なテキスト結合であればことたりますが、ある程度複雑な処理を行う場合、可読性の欠如や、複数行に渡る文字列を簡潔に表現できないというような点が問題になってきます。</p>

<h2>Template literalを使った文字組み立て</h2>

<p>Template literalを使えば、上記の文字組み立てを、以下のように書くことができます。</p>

<p></p><pre class="crayon-plain-tag">var name = 'john';
var country = 'japan';

var str1 = `Hello! My name is ${name}. I live in ${country}.`;

console.log(str1); // "Hello! My name is john. I live in japan."</pre><p></p>

<p>&#96;&#96;で囲まれた部分がTemplate literalです。この中で<code>${name}</code>、<code>${country}</code>という部分がありますが、ここはそれぞれ、<code>"john"</code>、<code>"japan"</code>と、変数の内容に置き換わります。このように、Template literal内の<code>${}</code>部分は、その内容が評価された結果に置き換えられ、最終的な処理結果が文字列として変数<code>str1</code>に格納されます。</p>

<h2>式の展開</h2>

<p><code>${}</code>の中には、変数だけでなく、式を入れることができます。例えば、以下の例を見て下さい。</p>

<p></p><pre class="crayon-plain-tag">var str1 = `今月: ${(new Date).getMonth()+1}月`;

console.log(str1); // "今月: 10月"</pre><p></p>

<p>上記例では、<code>Date</code>を利用し、現在の月を表示させています。<code>(new Date).getMonth()+1</code>の結果は現在の月で、例えばこの原稿執筆時では<code>10</code>となりますが、このような計算結果を、あらかじめ変数に入れておかずとも、<code>${}</code>内で展開させることも可能です。</p>

<p>JavaScriptを用いて複雑なテキストの組み立て処理を行いたい場合、Handlebarsやmustacheといった、文字列処理を抽象化したテンプレートエンジンが利用されてきました。</p>

<ul>
<li><a href="http://handlebarsjs.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Handlebars.js: Minimal Templating on Steroids</a></li>
<li><a href="https://mustache.github.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">{{ mustache }}</a></li>
</ul>

<p>このようなライブラリを利用すれば、今解説したような、テンプレート的な文字列処理を行えるのですが、そういった処理がある程度、素のJavaScriptでできるようになります。</p>

<h2>タグ付テンプレート</h2>

<p>Template literalにはタグという機能（Tagged template strings）があります。タグを利用すると、テンプレートの処理内容を、functionで具体的に指定することができます。その仕組みを理解するため、まずは単純な例を見てみます。</p>

<p></p><pre class="crayon-plain-tag">var marginVal = '30px';
var paddingVal = '40px';

function tag(strings, ...values) {
  console.log(strings); // ["marginは", "で、paddingは", "です"]
  console.log(values);  // ["30px", "40px"]
  return 'returned strings!';
};

var str1 = tag `marginは${marginVal}で、paddingは${paddingVal}です`;

console.log(str1); // "returned strings!"</pre><p></p>

<p>ここで使われているTemplate literalの頭には、<code>tag</code>という文字があります。これがタグの指定で、<code>tag</code>というfunctionで、テンプレートの処理内容を定義していることを示します。タグとして指定されたfunctionは、テンプレート内の文字列、変数を受け取ることができます。そして、このfunctionの返す値が、Template literalの処理結果となります。</p>

<p>もし、このTemplate literalにタグが指定されていない場合、コンソールに表示される結果は「marginは30pxで、paddingは40pxです」となりますが、タグが指定されているため、そのようにはなりません。</p>

<p>以降は、この例で登場しているfunction、<code>tag</code>を眺めながらご確認下さい。</p>

<p>タグとして指定されたfunctionは、第一引数に、テンプレート内で使われている文字列が、登場する順に格納された配列を受け取ります。この場合ですと、処理する対象は「<code>marginは${marginVal}で、paddingは${paddingVal}です</code>」で、この中で使われている文字列は、以下の3つです。</p>

<ul>
<li>&#8220;marginは&#8221;</li>
<li>&#8220;で、paddingは&#8221;</li>
<li>&#8220;です&#8221;</li>
</ul>

<p>これらが配列になって渡ってくるのが第一引数。第二引数以降で、これら文字列の間に挟まっている<code>${}</code>で展開される式の結果が渡されます。ここでは、以下の値を<code>values</code>として受け取っています。(※1)</p>

<ul>
<li>&#8220;30px&#8221;</li>
<li>&#8220;40px&#8221;</li>
</ul>

<p>そして最終的にfunctionが返した値が、テンプレートの処理結果となります。この場合ですと、<code>"returned strings!"</code>という文字列を返しているので、<code>str1</code>に入るのは<code>"returned strings!"</code>という文字列となり、これがコンソールに表示される結果となります。</p>

<p>こんなふうにして、受け取った値を好きに加工してくださいというのがタグ付きテンプレートです。この例では、最終的に返した値が、受け取った値を一切使っていませんが、ひとまずのタグの仕組みの理解のためそうしています。</p>

<p>ちなみに、以下例のように、<code>${}</code>と<code>${}</code>の間に何も文字がない場合、空文字が渡されます。いきなり<code>${}</code>から始まる場合はその前に空文字が、<code>${}</code>で終わる場合はその後に空文字があるものとして扱われます。</p>

<p></p><pre class="crayon-plain-tag">var val1 = 'value1';
var val2 = 'value2';

function tag(strings, ...values) {
  console.log(strings, values);
};

var str1 = tag `${val1}`;        // ["", ""], ["value1"]
var str1 = tag `${val1}${val2}`; // ["", "", ""], ["value1", "value2"]</pre><p></p>

<p><small>
※1: <code>...values</code>と引数に書かれていますが、これは、残りの引数を配列にまとめて受け取ることのできる、ES6の<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Rest parameters</a>という機能を利用しています。
</small></p>

<h2>タグを利用して大文字に変換する例</h2>

<p>このタグを利用し、テンプレート内に埋め込まれた文字列を大文字にしてみたのが、以下の例です。</p>

<p></p><pre class="crayon-plain-tag">var charsToUpper = function(strings, ...values) {
  var res = '';
  for(var i=0, l=strings.length; i&lt;l; i+=1) {
    res += strings[i];
    if(i &lt; values.length) {
      res += values[i].toUpperCase();
    }
  }
  return res;
};

var name = &#039;john&#039;;
var country = &#039;japan&#039;;

var str1 = charsToUpper `Hello! My name is ${name}. I live in ${country}.`;
var str2 = charsToUpper `${name} ${country}`;

console.log(str1); // &quot;Hello! My name is JOHN. I live in JAPAN.&quot;
console.log(str2); // &quot;JOHN JAPAN&quot;</pre><p></p>

<p>テンプレート内で利用されている変数<code>name</code>、<code>country</code>にはそれぞれ、<code>"john"</code>、<code>"japan"</code>と、小文字の文字列が入っていますが、テンプレートの処理結果は、<code>"Hello! My name is JOHN. I live in JAPAN."</code>と、大文字に置き換わっています。タグとして指定された<code>charsToUpper</code>の内容を見ると、登場する順に文字列と変数の内容を結合し、その中で、<code>${}</code>で埋め込まれた文字列に関しては、<code>.toUpperCase()</code>で大文字にしているのが確認できます。</p>

<h2>ブログ記事用のHTMLを展開する例</h2>

<p>最後に、ちょっと長いですが、ブログ記事のようなものをHTMLとして出力するようなケースを想定した例を紹介します。</p>

<p></p><pre class="crayon-plain-tag">var data = {
  title: '&lt;探検&gt;！ECMAScript',
  author: '佐藤鈴木&amp;田中太郎',
  tags: [ 'HTML', 'JavaScript', 'CSS' ],
  links: [
    { 
      title: 'Mozilla Developer Network',
      href: 'https://developer.mozilla.org/ja/'
    },
    {
      title: 'Web Hypertext Application Technology Working Group',
      href: 'https://whatwg.org/'
    }
  ],
  entryBody: '&lt;p&gt;This is a blog post!&lt;/p&gt;'
};

// HTMLの特殊文字を実体参照にするタグ
function htmlEscape(strings, ...values) {
  var handleString = function(str) {
    return str.replace(/&amp;/g, '&amp;amp;')
              .replace(/&gt;/g, '&amp;gt;')
              .replace(/&lt;/g, '&amp;lt;')
              .replace(/&quot;/g, '&amp;quot;')
              .replace(/'/g, '&amp;#039;')
              .replace(/`/g, '&amp;#096;');
  };
  var res = '';
  for(var i=0, l=strings.length; i&lt;l; i+=1) {
    res += handleString(strings[i]);
    if(i &lt; values.length) {
      res += handleString(values[i]);
    }
  }
  return res;
};

var html = `
  &lt;section class=&quot;entry&quot;&gt;
    &lt;header&gt;
      &lt;h1&gt;${htmlEscape `${data.title}`}&lt;/h1&gt;
      &lt;div class=&quot;author&quot;&gt;Author: ${htmlEscape `${data.author}`}&lt;/div&gt;
      &lt;ul class=&quot;tags&quot;&gt;
        ${data.tags.map(function(tag) { return `&lt;li&gt;${tag}&lt;/li&gt;` }).join('\n')}
      &lt;/ul&gt;
    &lt;/header&gt;
    ${data.entryBody}
    &lt;hr&gt;
    &lt;dl&gt;
      &lt;dt&gt;関連リンク&lt;/dt&gt;
      ${data.links.map(function(link) { return `&lt;dd&gt;&lt;a href=&quot;${link.href}&quot;&gt;${link.title}&lt;/dd&gt;` }).join('\n')}
    &lt;/dl&gt;
  &lt;/section&gt;
`;

console.log(html);</pre><p></p>

<p>このコードで出力されるのは、以下の文字列です。（見やすさのためにインデントを調節しています）</p>

<p></p><pre class="crayon-plain-tag">&lt;section class="entry"&gt;
  &lt;header&gt;
    &lt;h1&gt;&amp;lt;探検&amp;gt;！ECMAScript&lt;/h1&gt;
    &lt;div class="author"&gt;Author: 佐藤鈴木&amp;amp;田中太郎&lt;/div&gt;
    &lt;ul class="tags"&gt;
      &lt;li&gt;HTML&lt;/li&gt;
      &lt;li&gt;JavaScript&lt;/li&gt;
      &lt;li&gt;CSS&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/header&gt;
  &lt;p&gt;This is a blog post!&lt;/p&gt;
  &lt;hr&gt;
  &lt;dl&gt;
    &lt;dt&gt;関連リンク&lt;/dt&gt;
    &lt;dd&gt;&lt;a href="https://developer.mozilla.org/ja/"&gt;Mozilla Developer Network&lt;/dd&gt;
    &lt;dd&gt;&lt;a href="https://whatwg.org/"&gt;Web Hypertext Application Technology Working Group&lt;/dd&gt;
  &lt;/dl&gt;
&lt;/section&gt;</pre><p></p>

<p>このサンプルでは、コードの頭で用意しているオブジェクト<code>data</code>の内容を、テンプレートに展開しています。</p>

<p>その処理内容の中で、タグ<code>htmlEscape</code>を使っています。このfunctionは、受け取った値の中に含まれるHTMLの特殊文字を実体参照に変換し、ひとつに結合して返します。ここでは、タイトル部分と著者名部分に使われており、出力結果には&#8220;、<code>&amp;amp;</code>がそれぞれ実体参照に置き換わっているのが確認できます。</p>

<p>このほか、タグやリンクからリストを作っている箇所では、<code>${}</code>の中で<code>map</code>(※2)を使い、配列をli要素の繰り返しに変換しています。単純な処理であれば、このようにテンプレート内で何らかの処理を行わせてしまってもよいですし、ある程度複雑な処理であれば、別途functionとして分け、<code>${}</code>内でそのfunctionを呼び出すというような方法を取るのもよさそうです(※3)。</p>

<p><small>
※2: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Array.prototype.map</a>は、配列の各要素それぞれに対して、渡されたfunctionを実行し、その結果から新しい配列を作る機能です。</p>

<p>※3: ES6で追加された<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Arrow function</a>を使えば、このテンプレート内で<code>map</code>が使用されている箇所を、以下のように簡潔に書くことができます。
</small></p>

<p></p><pre class="crayon-plain-tag">${data.tags.map(tag =&gt; `<li>${tag}</li>`).join('\n')}</pre><p></p>

<p></p><pre class="crayon-plain-tag">${data.links.map(link =&gt; `<dd><a href="${link.href}" data-wpel-link="internal">${link.title}</dd>`).join('\n')}</pre><p></p>

<h2>ブラウザ対応状況</h2>

<p>以下のサイトのES6対応テーブルを見ると、Template literal (Template strings)は、IEを除く最新版のモダンブラウザ（Microsoft Edgeは可）で利用可能なようです。各ブラウザの対応はかなり進んでいると言えそうですが、bable等のトランスパイラを利用しない場合、IE11、iOS8のSafariではまだ対応していないというあたりが、現実的に利用可能かを判断するボーダーラインとなりそうです。</p>

<ul>
<li><a href="https://kangax.github.io/compat-table/es6/#test-template_strings">ECMAScript 6 compatibility table</a></li>
</ul>

<h2>まとめ</h2>

<p>以上、Template literalについて、その概要を解説しました。Template literalを用いれば、文字列の結合処理をとても簡潔に書くことができるようになります。複雑なテンプレート処理の場合ははやり、テンプレートエンジンのような仕組みを利用したほうが良いケースが多いように筆者は感じますが、ちょっとした文字列処理の際には、基本、Template literalを使っていくようになるのではないでしょうか。</p>

<p>Template literalについてより詳しく知りたい場合、以下が参考になります。</p>

<ul>
<li><a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/template_strings" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Template strings &#8211; JavaScript | MDN</a></li>
<li><a href="http://ponyfoo.com/articles/es6-template-strings-in-depth" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ES6 Template Literals in Depth</a></li>
<li><a href="http://www.sitepoint.com/es6-now-template-strings/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ES6 for Now: Template Strings</a></li>
</ul>
]]></content:encoded>
		
		<series:name><![CDATA[ECMAScript 2015（ECMAScript 6）特集]]></series:name>
	</item>
		<item>
		<title>JavaScriptにもクラスがやってきた！JavaScriptの新しいclass構文をマスターしよう</title>
		<link>/takazudo/17355/</link>
		<pubDate>Fri, 16 Oct 2015 04:00:17 +0000</pubDate>
		<dc:creator><![CDATA[高津戸壮]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">/?p=17355</guid>
		<description><![CDATA[連載： ECMAScript 2015（ECMAScript 6）特集 (6)ECMAScript 2015（ECMAScript 6）で新たに追加された待望のclass構文について、その概要をサンプルコードを交えて紹介...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/ecma2015/" class="series-336" title="ECMAScript 2015（ECMAScript 6）特集" data-wpel-link="internal">ECMAScript 2015（ECMAScript 6）特集</a> (6)</div><p>ECMAScript 2015（ECMAScript 6）で新たに追加された待望のclass構文について、その概要をサンプルコードを交えて紹介します。</p>

<p><img src="/wp-content/uploads/2015/10/Ecma_RVB-003.jpg" alt="" width="373" height="146" class="aligncenter size-full wp-image-17453" srcset="/wp-content/uploads/2015/10/Ecma_RVB-003.jpg 373w, /wp-content/uploads/2015/10/Ecma_RVB-003-300x117.jpg 300w, /wp-content/uploads/2015/10/Ecma_RVB-003-207x81.jpg 207w" sizes="(max-width: 373px) 100vw, 373px" /></p>

<h2>これまでのJavaScriptにおけるクラス</h2>

<p>多くのプログラミング言語はクラスを作れる機能を持っていますが、JavaScriptにその機能は用意されていませんでした。しかし、JavaScriptにはprototypeという柔軟な仕組みが存在しており、このprototypeを利用することで、他の言語で表現されている「クラス」と似たような振る舞いを再現することが可能でした。</p>

<p>それは例えば、こんなふうにです。</p>

<p></p><pre class="crayon-plain-tag">/* Cat雛形の作成 */

function Cat(name) {
  this.setName(name);
};
Cat.prototype = {
  setName: function(name) {
    this._name = name;
  },
  getName: function() {
    return this._name;
  },
  walk: function() {
    console.log(this._name + 'が歩いてます');
  }
};

/* Catからオブジェクトを作成 */

var cat1 = new Cat('タマ');
var cat2 = new Cat('コタロー');
cat1.walk(); // タマが歩いています
cat2.walk(); // コタローが歩いています</pre><p></p>

<p>コンストラクタであるfunction <code>Cat</code>を宣言し、その<code>prototype</code>にインスタンスメソッド群を定義したオブジェクトを指定します。すると、<code>new Cat</code>した時、作成されたオブジェクトのプロパティは、そのオブジェクト自身に直接定義されていない場合、<code>Cat.prototype</code>に定義されている同名のプロパティを参照するという具合です。</p>

<p>このように、単純なオブジェクトの雛形を作るだけならまだよいのですが、あるクラスを継承し、別のクラスを作る、いわゆる「クラスの継承」を表現するのはちょっと複雑です。その実装方法についてはここでは割愛しますが、例えばこの<code>Cat</code>であれば、より上位の概念を表現したクラス<code>Animal</code>を用意し、<code>Cat</code>は<code>Animal</code>を継承して作られる……というような場合です。複雑と言っても、よく使われる概念ではあるので、これまでは多くのライブラリやトランスパイラがこの機能を担っていました。</p>

<p>このような、prototypeを利用した「クラス」的な振る舞いの実装は、JavaScript初学者のひとつのハードルになっていたと言ってもよいのではないでしょうか。</p>

<h2>ES6のclass構文</h2>

<p>そんな「クラス」を実現するclass構文が、ES6では用意されました。</p>

<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Classes &#8211; JavaScript | MDN</a></li>
<li><a href="http://www.ecma-international.org/ecma-262/6.0/#sec-class-definitions" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript 2015 Language Specification &#8211; Class Definitions</a></li>
</ul>

<p>class構文を使えば、クラスの継承も簡単に行えます。その仕様の実態は、prototypeベースの継承であり、単なる糖衣構文に過ぎませんが、複雑な実装をすることなく誰でも簡単にクラスを扱えるようになったことは大きな意味があると言ってよいでしょう。</p>

<p>先ほどの<code>Cat</code>を、ES6のclass構文で書くと、以下のようになります。</p>

<p></p><pre class="crayon-plain-tag">/* Catクラス */

class Cat {
  constructor(name) {
    this.name = name;
  }
  set name(name) {
    this._name = name;
  }
  get name() {
    return this._name;
  }
  walk() {
    console.log(this._name + 'が歩いてます');
  }
}

/* Catクラスのインスタンス作成 */

var cat1 = new Cat('タマ');
var cat2 = new Cat('コタロー');
cat1.walk(); // タマが歩いています
cat2.walk(); // コタローが歩いています</pre><p></p>

<p>これで先ほどと同様の実行結果になります。</p>

<p>※ ここで使っている<code>set</code>はsetter、<code>get</code>はgetterとしてES5で定義されている構文、<code>walk</code>メソッドを定義しているのはMethod definitionで、ES6で定義されている構文です。class構文とはまた別なので注意して下さい。</p>

<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">setter &#8211; JavaScript | MDN</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">getter &#8211; JavaScript | MDN</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Method definitions &#8211; JavaScript | MDN</a></li>
</ul>

<h2>静的メソッド</h2>

<p>class構文は、静的メソッド※の定義方法も用意しています。先ほどの<code>Cat</code>に、作成した猫の数を返す<code>count</code>メソッドを実装してみたのが以下です。</p>

<p>※クラスのインスタンスを作らずとも呼べるメソッドのことを言います。</p>

<p></p><pre class="crayon-plain-tag">var catCount = 0; // 作った猫の数

/* Catクラス */

class Cat {
  constructor(name) {
    this.name = name;
    catCount += 1; // 作った猫の数を+1
  }
  set name(name) {
    this._name = name;
  }
  get name() {
    return this._name;
  }
  walk() {
    console.log(this._name + 'が歩いてます');
  }
  /* 静的メソッド */
  static count() {
    return catCount;
  }
}

/* Catクラスのインスタンス作成 */

console.log(Cat.count()); // 0
var cat1 = new Cat('タマ');
console.log(Cat.count()); // 1
var cat2 = new Cat('コタロー');
console.log(Cat.count()); // 2</pre><p></p>

<p><code>Cat</code>の<code>constructor</code>が実行されると猫の匹数を示す<code>catCount</code>がインクリメントされ、静的メソッドの<code>count()</code>が呼ばれると、この<code>catCount</code>を返します。</p>

<p>※ ちなみに、メソッド以外の静的なプロパティを設定すること（ここだと例えば<code>Cat.catCount</code>に猫の数を格納するようなこと）は、class構文には今のところ用意されていないようです。これについては2015年10月現在、proposalが出ているだけの状態で、今後どうなるかはまだ分かりません。</p>

<ul>
<li><a href="https://github.com/jeffmo/es-class-static-properties-and-fields" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">GitHub &#8211; jeffmo/es-class-static-properties-and-fields</a></li>
<li><a href="http://stackoverflow.com/questions/22528967/es6-class-variable-alternatives" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">javascript &#8211; ES6 class variable alternatives &#8211; Stack Overflow</a></li>
</ul>

<h2>クラスの継承</h2>

<p>クラスを継承し、別のクラスを作るには、<code>extends</code>を使います。以下は、<code>Animal</code>を継承した<code>Cat</code>クラスを定義した例です。</p>

<p></p><pre class="crayon-plain-tag">/* Animalクラス */

class Animal {
  constructor(name) {
    this.name = name;
  }
  set name(name) {
    this._name = name;
  }
  get name() {
    return this._name;
  }
  walk() {
    console.log(this.name + 'が歩いてます');
  }
}

/* Catクラス */

class Cat extends Animal { // Animalを継承したCatクラスを定義
  mew() {
    console.log(this.name + 'がニャーと鳴いてます');
  }
}

/* Catクラスのインスタンス作成 */

var cat1 = new Cat('タマ');
console.log(cat1.name); // タマ
cat1.walk(); // タマが歩いてます
cat1.mew();  // タマがニャーと鳴いてます

var cat2 = new Cat('コタロー');
console.log(cat2.name); // コタロー
cat2.walk(); // コタローが歩いてます
cat2.mew();  // コタローがニャーと鳴いてます</pre><p></p>

<p><code>Cat</code>のインスタンスオブジェクトである<code>cat1</code>、<code>cat2</code>は、<code>Cat</code>に定義されているメソッドが利用できるだけではなく、<code>Animal</code>に定義されている<code>constructor</code>で初期化され、<code>Animal</code>で定義されているメソッドを利用できていることが分かります。</p>

<h2>継承元のメソッド呼び出し</h2>

<p>クラスを継承した場合、継承元のメソッドを呼びたいことがあります。その場合、以下のように<code>super</code>を使います。</p>

<p></p><pre class="crayon-plain-tag">/* Catクラス */

class Cat extends Animal {
  constructor(name, color) {
    super(name); // Animalクラスのconstructor呼び出し
    this.color = color;
  }
  get color() {
    return this._color;
  }
  set color(color) {
    this._color = color;
  }
  mew() {
    console.log(this.color + '色の' + this.name + 'がニャーと鳴いてます');
  }
  walk() {
    super.walk(); // Animalクラスのwalkメソッド呼び出し
    console.log('忍び足です');
  }
}

/* Catクラスのインスタンス作成 */

var cat1 = new Cat('タマ', '茶');
console.log(cat1.name); // タマ
cat1.walk(); // タマが歩いてます
             // 忍び足です
cat1.mew();  // 茶色のタマがニャーと鳴いてます

var cat2 = new Cat('コタロー', '黒');
console.log(cat2.name); // コタロー
cat2.walk(); // コタローが歩いてます
             // 忍び足です
cat2.mew();  // 黒色のコタローがニャーと鳴いてます</pre><p></p>

<p><code>constructor</code>内で、<code>super(name)</code>と、<code>Animal</code>の<code>constructor</code>を実行し、<code>walk()</code>内で<code>super.walk()</code>と、<code>Animal</code>の<code>walk</code>を実行しています。</p>

<p>class構文を使わない場合、<code>Animal.prototype.walk.apply(this, arguments)</code>などと、継承元のメソッドを<code>prototype</code>経由で直接参照し、<code>apply</code>でコンテキストを自分にして実行するなどというような実装が必要です。<code>super</code>を使えば、同じ内容をとてもシンプルに書くことができます。</p>

<h2>その他注意点</h2>

<p>他、筆者がclass構文を使ってみて気になったこととして、インスタンスのプロパティを<code>prototype</code>直下に直接指定できないという点が気になりました。例えば、はじめに挙げた<code>Cat</code>でインスタンス作成時に<code>name</code>を受け取らない場合、以下のように書けば、<code>setName</code>する前に<code>getName</code>が呼ばれた場合、<code>'名無しの猫'</code>が名前として返ります。</p>

<p></p><pre class="crayon-plain-tag">/* Cat雛形の作成 */

function Cat() {};
Cat.prototype = {
  _name: '名無しの猫', /* _nameの初期値として指定 */
  setName: function(name) {
    this._name = name;
  },
  getName: function() {
    return this._name;
  },
  walk: function() {
    console.log(this._name + 'が歩いてます');
  }
};</pre><p></p>

<p>しかし、ES6のclass構文では、class宣言時に設定できるのはメソッドのみです。上記例のように<code>_name</code>を<code>prototype</code>に指定することができません。インスタンスのプロパティの初期値を設定したい場合、<code>constructor</code>内で設定する必要があります。</p>

<p>※<code>prototype</code>直下にオブジェクトを指定した場合、全てのインスタンスで同一のオブジェクトを参照してしまい、思わぬバグの原因になったりすることもありえるため、このような書き方をそもそもしないほうがよいという見解もあります。</p>

<h2>ブラウザ対応状況</h2>

<p>class構文の対応状況は、2015年10月現在、まだまだといった状況です。</p>

<ul>
<li><a href="http://kangax.github.io/compat-table/es6/#test-class" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript 6 compatibility table</a></li>
</ul>

<p>筆者が確認したタイミングで対応しているのは、Safari9 (Webkit)だけです。デベロッパー版や設定フラグなど考慮すると Chrome45 (enable-javascript-harmonyをオンにし、strict modeのみで動作)、Firefox nightly (v44)、Microsoft Edge（experimental featureをオンにして使用）などで利用できます。一般的な閲覧環境を想定する場合、class構文を使用するのはまだ先だと考えておいてよいでしょう。bableやtraceur等のトランスパイラは対応しています。ただし、まだclass構文の全ての機能に対応しているわけではないようです。</p>

<p>ちなみに筆者は、本稿を書くためのサンプルを、Chrome canaryで動作することを確認しています。</p>

<h2>まとめ</h2>

<p>以上、ES6のclass構文について、その概要を簡単に紹介しました。筆者は、好きでよく<a href="http://coffeescript.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">CoffeeScript</a>を使っていたのですが、CoffeeScriptを使う大きな理由の一つとして、CoffeeScript独自のclass構文が使えるようになっているというところがありました。そういったコードの設計の根幹部分が言語として用意された状態だと、コードの見通しがよくなるなぁと感じていまして。しかし、ES6にてclass構文が実装されたとなれば、自分がCoffeeScriptを選択する理由が一つ、なくなった感じがします。</p>

<p>ほか、class構文を使って書かれたコードは、そのコードで表現したいことが、同様の内容をclass構文を使わないで書いた場合よりも、よりシンプルに表現できているように感じます。これは、チーム間でのコミュニケーション効率を高め、開発をスムーズにするかもしれません。</p>

<p>class構文がやってくれることは、これまでJavaScriptで書かれてきたいわゆる「クラス」的なものの実装そのものであるため、class構文を使ったからといって、これまで書いてきたJavaScriptと根本的に設計が変わってしまうということはないでしょう。ブラウザの対応はまだまだのようですが、babelをお供に、開発に採用できるケースはかなり多いのではないかと思います。</p>
]]></content:encoded>
		
		<series:name><![CDATA[ECMAScript 2015（ECMAScript 6）特集]]></series:name>
	</item>
		<item>
		<title>Promiseで簡単！JavaScript非同期処理入門【後編】</title>
		<link>/takazudo/17113/</link>
		<pubDate>Mon, 05 Oct 2015 00:00:01 +0000</pubDate>
		<dc:creator><![CDATA[高津戸壮]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">/?p=17113</guid>
		<description><![CDATA[連載： ECMAScript 2015（ECMAScript 6）特集 (5)前回に引き続き、ECMAScript 2015（ECMAScript 6）で新たに追加されたPromiseについて、その概要を全2回に渡って紹...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/ecma2015/" class="series-336" title="ECMAScript 2015（ECMAScript 6）特集" data-wpel-link="internal">ECMAScript 2015（ECMAScript 6）特集</a> (5)</div><p>前回に引き続き、ECMAScript 2015（ECMAScript 6）で新たに追加されたPromiseについて、その概要を全2回に渡って紹介します。今回は後編です。</p>

<h2>前回のおさらい</h2>

<p>前回は、こんなふうにPromiseを使うという例を紹介しました。それは、以下のようにAjaxでAPIにアクセスする例でした。</p>

<p></p><pre class="crayon-plain-tag">var fetchSomething1 = function() {
  return new Promise(function(resolve, reject) {
    // API1にアクセス
    doAjaxStuff(someOptions1, {
      success: function(data) { // 成功した場合
        resolve();
      },
      fail: function() { // 何かしらエラーが発生した場合
        reject({ message: 'APIにアクセスできませんでした' });
      }
    });
  });
};

fetchSomething1().then(function() { // A: fetchSomething1の成功時に実行される
  alert('API1よりデータを取得しました');
}, function(error) { // B: fetchSomething1の失敗時に実行される
  alert('API1よりデータを取得できませんでした。エラーメッセージ: ' + error.message);
});</pre><p></p>

<p>ここで定義している<code>fetchSomething1</code>は、Promiseオブジェクトを返します。AjaxでAPIにアクセスするのが成功した場合、<code>then</code>の第一引数に指定したfunctionが、失敗した場合、<code>then</code>の第二引数に指定したfunctionが実行されるのでした。</p>

<p>以降、便宜上、<code>then</code>の第一引数に指定されたfunctionのことをonFulfilledハンドラ、第二引数に指定されたfunctionのことをonRejectedハンドラと呼ぶことにします。</p>

<h2>Promiseインターフェイスの実装例: Fetch API</h2>

<p>このPromise、今後はJavaScriptを書いていく上での基本的な知識となっていくことが、ほとんど確実と言ってよいだろうと筆者は考えます。</p>

<p>例えば、WHATWGで策定されている<a href="https://fetch.spec.whatwg.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Fetch API</a>は、Promiseをベースに作られています。以下の例では、同階層にある<code>memo.txt</code>の内容をFetch APIを利用して取得、そのファイルの内容を<code>console.log</code>しています。</p>

<p></p><pre class="crayon-plain-tag">fetch('./memo.txt')
  .then(function(response) {
    response.text().then(function(text) {
      console.log(text); // memo.txtの内容
    });
  }, function(error) {
    console.log(error);
  });</pre><p></p>

<p>Fetch APIについての知識がなかったとしても、Promiseに慣れていれば、上記コードがどのような意味を持っているかを想像するのは容易でしょう。今後、ブラウザやECMAScript自体が実装していく非同期に処理を行うAPIについても、Promiseをベースとしていくであろうと想像されます。</p>

<p>なお、このコード内では、<code>response.text()</code>でレスポンス内容のテキストを取得しています。この処理自体も非同期で実装されており、その結果を<code>then</code>で受け取るようになっています。</p>

<h2>インターフェースを統一できるのもPromiseのメリット</h2>

<p>初めに挙げたAjaxする例ですが、コレ、<code>then</code>を使って、Ajaxの成功時、失敗時に指定したfunctionを実行させているわけですが、前編で紹介したコールバックを使っても実装可能です。例えばこんなふうにしたっていいじゃないですか。</p>

<p></p><pre class="crayon-plain-tag">fetchSomething1(function() {
  // 成功時の処理
}, function() {
  // エラー時の処理
});</pre><p></p>

<p>第一引数に成功時の処理を、第二引数にエラー時の処理を。これでも問題ないです。はたまた、こんなのはどうでしょう。各種オプションを渡せるようにしました。</p>

<p></p><pre class="crayon-plain-tag">fetchSomething1(params, method, noCache, {
  success: function() {
    // 成功時の処理
  },
  fail: function() {
    // エラー時の処理
  }
});</pre><p></p>

<p>やりかたはいろいろとあります。どの方法が一番良いのでしょう？それぞれメリット、デメリットがあるかもしれませんが、ひとつ言えることは、各々が、それぞれの方法でバラバラな書き方をしてしまうことがあり得るということです。</p>

<p>Promiseを利用すれば、非同期処理の書き方を統一できます。成功か失敗か。結果が単純にその2つに分かれる非同期処理において、それを担うfunctionがPromiseオブジェクトを返してくれるのであれば、結果を受け取った方は、以降の処理を<code>then</code>で書くものと理解することができます。</p>

<p>これはあくまで、そのように書くよう統一しておけば、多くの人が理解しやすいコードにできますというだけのことではあるのですが、PromiseがES6に採用されたことで、非同期処理の扱いには、Promiseをベースにしていくのが基本となっていくことはほとんど確実と言えるのではないでしょうか。</p>

<h2>順次処理を行わせる</h2>

<p>前回、コールバックを使いAPIに順番にアクセスすると、以下のようになってしまうという例を挙げました。</p>

<p></p><pre class="crayon-plain-tag">/* 順番に実行 */

fetchSomething1(function() {
  fetchSomething2(function() {
    fetchSomething3(function() {
      fetchSomething4(doSomethingFinally); // 全部終わったら doSomethingFinally()
    });
  });
});</pre><p></p>

<p>そして先ほど、この<code>fetchSomething1</code>を、Promiseをベースにした書き方にしてみたわけですが、他のfunctionも同様にPromiseベースで書き直し、それぞれがPromiseオブジェクトを返すようにすると、上記コードは以下のように書き直せます。</p>

<p></p><pre class="crayon-plain-tag">fetchSomething1()
  .then(fetchSomething2)
  .then(fetchSomething3)
  .then(fetchSomething4)
  .then(doSomethingFinally);</pre><p></p>

<p>何段階にも入れ子になってしまうfunctionよりも、こちらのほうがコードの見通しがよいのではないでしょうか。</p>

<p><code>fetchSomething1</code>〜<code>fetchSomething4</code>はそれぞれ、Promsieオブジェクトを返します。<code>then</code>に指定されたfunction内でPromiseオブジェクトが返された場合、<code>then</code>の返す値自体が、そのPromiseオブジェクトとなります。上記を一つずつ分けて書くと、以下のようになります。</p>

<p></p><pre class="crayon-plain-tag">var promise1 = fetchSomething1();
var promise2 = promise1.then(fetchSomething2);
var promise3 = promise2.then(fetchSomething3);
var promise4 = promise2.then(fetchSomething4);
promise4.then(doSomethingFinally);</pre><p></p>

<p>各functionはそれぞれのPromiseを返し、続けて書いた処理は、前のPromiseが<code>fulfilled</code>になった時に初めて実行されます。<code>fetchSomething2</code>は<code>fetchSomething1</code>の返すPromiseが<code>fulfilled</code>になった時に実行され、<code>fetchSomething3</code>は<code>fetchSometing2</code>の返すPromiseが<code>fulfilled</code>になった時に実行され……と、非同期処理が連鎖するように動作します。</p>

<p>Promiseを使えば、このように連続した非同期処理を簡潔に記述することが可能になります。</p>

<h2>同期的な処理も混ぜる</h2>

<p>そのように非同期処理をうまく扱えるようにするPromiseですが、その途中に同期的な処理を挟むこともできます。</p>

<p>以下で用意した各functionはそれぞれ、非同期的に扱う必要のない処理たちですが、渡された数値を2倍にして返す<code>double</code>と、渡された数値を3倍にして返す<code>treble</code>は、Promiseオブジェクトを返し、計算が終わったらその結果を後続する処理に渡すようにしています。</p>

<p>また、渡された数値をコンソールに表示するだけのfunction、<code>dump</code>は、<code>console.log</code>で渡された値を表示したあとは、そのままその数値を返しています。</p>

<p></p><pre class="crayon-plain-tag">/* 2倍にする */

var double = function(number) {
  return new Promise(function(resolve) {
    resolve(number * 2);
  });
};

/* 3倍にする */

var treble = function(number) {
  return new Promise(function(resolve) {
    resolve(number * 3);
  });
};

/* 表示する */

var dump = function(number) {
  console.log(number);
  return number;
}

/* 実行 */

double(10)       // 10*2 -&gt; 20
  .then(dump)    // コンソールに表示: 20
  .then(treble)  // 20*3 -&gt; 60
  .then(dump)    // コンソールに表示: 60
  .then(double)  // 60*2 -&gt; 120
  .then(dump);   // コンソールに表示: 120</pre><p></p>

<p><code>resolve</code>に渡した値は、後続する処理で受け取ることができるため、<code>double(10)</code>の結果は後続する<code>dump</code>に渡されます。function <code>dump</code>の内容は、<code>console.log</code>した後、渡された数値を返すだけです。このように、onFulfilledハンドラ内でPromiseオブジェクト以外が返された場合、新しくPromiseオブジェクトが作成され、返した値ですぐに<code>resolve</code>されます。例えば、上記コードで最初に<code>dump</code>している箇所は、処理内容的には以下と同じです。</p>

<p></p><pre class="crayon-plain-tag">double(10)       // 10*2 -&gt; 20
  .then(function(number) {
    return new Promise(function(resolve) {
      console.log(number); // コンソールに表示: 20
      resolve(number);
    });
  })    
  .then(treble)  // 20*3 -&gt; 60
  .then(dump)    // コンソールに表示: 60
  .then(double)  // 60*2 -&gt; 120
  .then(dump);   // コンソールに表示: 120</pre><p></p>

<p>このような仕組みが用意されているため、Promiseを使うことで、同期処理と非同期処理を自然に混ぜて記述することが可能になっています。</p>

<p>※ ちなみに、ここで用意したfunction<code>double</code>も、<code>treble</code>も、処理内容的には同期的なものですが、Promiseを介すと、非同期な処理として扱われます。</p>

<h2>並列処理</h2>

<p>非同期処理を扱う時、一つずつ順番に処理するのではなく、いくつかの処理を並列に走らせたい場合があります。例えば、何回か例に出している、AjaxでAPIにアクセスするfunction、<code>fetchSomething1</code>〜<code>fetchSomething4</code>であれば、これらを同時に実行し、すべての処理が終わったタイミングを知りたいというようなケースを考えてみます。そのような並列処理は、<code>Promise.all</code>を使うことで簡単に実装できます。以下にそのコード例を挙げます。</p>

<p></p><pre class="crayon-plain-tag">var promises = [
  fetchSomething1(),
  fetchSomething2(),
  fetchSomething3(),
  fetchSomething4()
];

Promise.all(promises)
  .then(function(results) {
    console.log(results[0]); // fetchSomething1のresolveに渡された値
    console.log(results[1]); // fetchSomething2のresolveに渡された値
    console.log(results[2]); // fetchSomething3のresolveに渡された値
    console.log(results[3]); // fetchSomething4のresolveに渡された値
    doSomethingFinally();
  }, function(error) {
    console.log(error); // 最初にrejectに渡された値
  });</pre><p></p>

<p><code>Promise.all</code>にPromiseオブジェクトの配列を渡すと、渡された全てのPromiseオブジェクトが<code>fulfilled</code>になった時、後続する<code>then</code>にて登録された処理が実行されます。このとき、各Promiseオブジェクト内で<code>resolve</code>に渡された値は、それぞれの結果をまとめた配列として受け取ることができます。上記コードだと、<code>then</code>のonFulfilledハンドラで受け取っている<code>results</code>がその配列です。</p>

<p>また、いずれかのPromiseオブジェクトが<code>rejected</code>になった場合、<code>then</code>のonRejectedハンドラが実行されます。この時、<code>rejected</code>にされたPromiseオブジェクト内で、<code>reject</code>に渡された値を受け取ることができます。</p>

<p>このような処理を<code>Promise.all</code>なしで書くには、コールバックのように一筋縄で済ませることはできません。各処理が終わったかどうかをフラグを立ててチェックしたりなど、なかなか地味な処理を書く必要がありそうです。しかし、Promiseがあれば簡潔に処理を記述することができます。</p>

<h2>エラーをまとめてキャッチ</h2>

<p><code>then</code>のonRejectedハンドラは、Promiseオブジェクトが<code>rejected</code>になったときに実行されます。この時、<code>then</code>にonRejectedハンドラが指定されていない場合、後続する<code>then</code>のonRejectedハンドラが実行されます。例えば以下のような例を見てみます。</p>

<p></p><pre class="crayon-plain-tag">fetchSomething1()
  .then(fetchSomething2) // A
  .then(doSomethingFinally, handleError); // B</pre><p></p>

<p>今までの例と同様、<code>fetchSomethingX</code>は、AjaxでAPIにアクセスする、非同期で、Promiseオブジェクトを返すfunctionです。ここで、<code>fetchSomething1</code>の中でエラーが発生し、<code>fetchSomething1</code>が返すPromiseオブジェクトが<code>rejected</code>になったとします。すると、上記コメントAで示した<code>then</code>に指定されたonRejectedハンドラが実行されるのですが、AにはonRejectedハンドラが指定されていません。その場合は、続きの<code>then</code>に指定されたonRejectedハンドラが実行されます。この結果、上記コメントBにて指定されているonRejectedハンドラ<code>handleError</code>が実行される結果となります。</p>

<p>これはエラーの発生をまとめて扱いたい際に便利な機能です。同様に順次AjaxでAPIにいくつもアクセスする場合、以下のようにエラー処理をまとめて行うことができます。</p>

<p></p><pre class="crayon-plain-tag">fetchSomething1()
  .then(fetchSomething2)
  .then(fetchSomething3)
  .then(fetchSomething4)
  .then(fetchSomething5)
  .then(doSomethingFinally, handleError);</pre><p></p>

<p>上記のように書けば、<code>fetchSomething1</code>〜<code>fetchSomething5</code>のどこかでPromiseがrejectされた場合、後続する<code>then</code>に指定されたonFulfilledハンドラは実行されず、<code>handleError</code>が実行されます。</p>

<p><code>then</code>の第二引数は省略可能なため、onFulfilledハンドラだけを指定することが可能ですが、このようにエラー処理だけを個別に書きたい場合、例えば以下のように書くことで、onRejectedハンドラだけを指定することができます。</p>

<p></p><pre class="crayon-plain-tag">fetchSomething1()
  .then(fetchSomething2)
  .then(doSomethingFinally)
  .then(null, handleError); // 第一引数にnull</pre><p></p>

<p>上記のように書いてもよいですが、Promiseは、上記と同様の動作をする<code>catch</code>というメソッドを用意しています。このような場合、<code>catch</code>を使い、以下のように書いたほうが簡潔なコードとなるでしょう。</p>

<p></p><pre class="crayon-plain-tag">fetchSomething1()
  .then(fetchSomething2)
  .then(doSomethingFinally)
  .catch(handleError);</pre><p></p>

<h2>ライブラリやPolyfill</h2>

<p>Promiseは、2015年9月現在、一般的に普及しているブラウザに十分対応されているという状況ではありません（<a href="http://caniuse.com/#search=Promise" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">caniuse &#8211; Promise</a>）。しかし、ブラウザの対応を待ってからでないと利用できないと類の機能ではありません。Promiseオブジェクトと同様の挙動が実現できればよいわけで、既に様々なライブラリ、Polyfillが存在し、広く使われています。ES6のPromiseが使えない環境であっても、これらライブラリを利用すれば、様々なプロジェクトに活用することができるでしょう。</p>

<ul>
<li><a href="https://github.com/petkaantonov/bluebird" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">petkaantonov/bluebird</a></li>
<li><a href="https://github.com/tildeio/rsvp.js/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">tildeio/rsvp.js</a></li>
<li><a href="https://github.com/getify/native-promise-only" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">getify/native-promise-only</a></li>
<li><a href="https://github.com/calvinmetcalf/lie" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">calvinmetcalf/lie</a></li>
<li><a href="https://github.com/kriskowal/q" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">kriskowal/q</a></li>
<li><a href="https://github.com/paulmillr/es6-shim" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">paulmillr/es6-shim</a></li>
</ul>

<h2>最後に</h2>

<p>以上、2回に渡り、Promiseの機能概要を紹介しました。普段からJavaScriptを使って開発をしている者としては、Promiseっていう機能がECMAScriptに追加されたぞ！と言うより、ついに標準仕様となったか…！と感じる人がほとんどなのではないでしょうか。筆者も、<a href="https://api.jquery.com/jquery.deferred/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">jQueryのDeferred</a>や、<a href="https://docs.angularjs.org/api/ng/service/$q" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">AngularJSの$q</a>を日常的に使っていたので、Promiseのインターフェイスには馴染みがあります。これからは、これまで以上に当たり前のようにPromiseが使われるようになっていくでしょうから、この機会に正しく仕様を理解しておきたいところです。</p>

<p>Promiseについてより詳しく知りたい場合、以下を参考にすることをおすすめします。</p>

<ul>
<li><a href="http://azu.github.io/promises-book/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">JavaScript Promiseの本</a></li>
<li><a href="http://exploringjs.com/es6/ch_promises.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Exploring ES6 &#8211; 25. Promises for asynchronous programming</a></li>
</ul>
]]></content:encoded>
		
		<series:name><![CDATA[ECMAScript 2015（ECMAScript 6）特集]]></series:name>
	</item>
		<item>
		<title>Promiseで簡単！JavaScript非同期処理入門【前編】</title>
		<link>/takazudo/17107/</link>
		<pubDate>Fri, 02 Oct 2015 00:00:35 +0000</pubDate>
		<dc:creator><![CDATA[高津戸壮]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">/?p=17107</guid>
		<description><![CDATA[連載： ECMAScript 2015（ECMAScript 6）特集 (4)ECMAScript 2015（ECMAScript 6）で新たに追加されたPromiseについて、その概要を全2回に渡って紹介します。 ひと...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/ecma2015/" class="series-336" title="ECMAScript 2015（ECMAScript 6）特集" data-wpel-link="internal">ECMAScript 2015（ECMAScript 6）特集</a> (4)</div><p>ECMAScript 2015（ECMAScript 6）で新たに追加されたPromiseについて、その概要を全2回に渡って紹介します。</p>

<h2>ひとつずつ処理されるJavaScript</h2>

<p>まず、Promiseについて解説する前に、基礎的なことではありますが、JavaScriptのコードがどのようにJavaScriptエンジンに処理されるかについて、軽く解説しておきましょう。例えば以下の様なコードがあったとします。</p>

<p></p><pre class="crayon-plain-tag">var result1 = 1 + 2; // 3
var result2 = result1 + 100; // 103

/* functionらを準備 */

var doSomething1 = function() {
  document.getElementById('price').value = result2;
};
var doSomething2 = function() {
  alert('計算結果: ' + result2);
};
var doSomething3 = function() {
  console.log('計算結果: ' + result2);
};

/* 実行 */

doSomething1();
doSomething2();
doSomething3();</pre><p></p>

<p>このコードを実行すると、まず、</p>

<p></p><pre class="crayon-plain-tag">var result1 = 1 + 2;</pre><p></p>

<p>が実行され、<code>result</code>には<code>3</code>が入ります。そして次に、</p>

<p></p><pre class="crayon-plain-tag">var result2 = result1 + 100;</pre><p></p>

<p>が実行され、<code>result2</code>には<code>103</code>が入ります。その後、3つのfunctionが準備され、<code>doSomething1()</code>、<code>doSomething2()</code>、<code>doSomething3()</code>と、準備したfunction群が順番に実行されます。JavaScriptは基本的にシングルスレッドであり、一つの処理が完了するまで次の処理が実行されないようになっています。</p>

<p>2行目の<code>result1 + 100</code>が実行できるのも、1行目で<code>result1</code>に<code>1 + 2</code>の結果が入っているからですし、3つのfunctionが実行できるのも、それよりも前に各functionが準備されたからです。そして、各function内で使用されている<code>result2</code>には、2行目で計算された<code>103</code>が入っています。当たり前と言えば当たり前ですが。</p>

<p>また、function <code>doSomething2</code>内には<code>alert</code>があり、実行されると「計算結果: 103」とダイアログが出現します。ここで、ユーザーがそのダイアログを閉じなければ、処理は先に進みません。ほか、非常に複雑な計算をしたりなどし、一つの処理にとても時間がかかる場合などでも、その処理が終わるまでは、次の処理が始まりません。</p>

<h2>非同期な処理</h2>

<p>そんなJavaScriptですが、後から任意の処理をさせる方法がもちろんありますし、普段から利用しているでしょう。その方法の一つとして、イベントの利用が挙げられます。</p>

<p></p><pre class="crayon-plain-tag">document.getElementById('img1').addEventListener('click', function() {
  alert('画像がクリックされました');
}, false);</pre><p></p>

<p>このように、<code>addEventListener</code>を使えば、img要素がクリックされたタイミングで任意の処理を走らせることができます。</p>

<p>ほか、<code>setTimeout</code>のような、処理の実行をスケジュールする組み込み関数を利用すれば、後から任意の処理を実行させることができます。例えば、<code>setTimeout</code>を以下のように使えば、指定したfunctionは5秒後に実行されることになります。</p>

<p></p><pre class="crayon-plain-tag">setTimeout(function() {
  alert('5秒経ったみたいです');
}, 5000);</pre><p></p>

<p>当然、このコードが実行された時、ブラウザが5秒間固まったままになってしまうわけではありません。imgのクリックについても同様、もちろん画像がクリックするまでブラウザが固まってしまうわけではありません。<code>addEventListener</code>や<code>setTimeout</code>は、functionを受け取り、時が来たらそのfunctionを実行するように作られています。渡したfunctionは、即座に実行されるわけではないため、非同期に処理されるといえます。</p>

<h2>コールバック</h2>

<p>JavaScripで書かれたプログラムでは、そのような非同期処理を行いたい場合、functionの受け渡しをを利用して実現されてきました。今例に挙げた<code>addEventListener</code>も<code>setTimeout</code>も、関数を受け取っている点に注目して下さい。このように、なにかしらの処理が完了したら渡したfunctionを実行させるという実装手法は、「コールバック」と呼ばれています。このコールバックを使って非同期処理を書くというスタイル、単純なケースであればシンプルで分かりやすいのですが、問題もあります。</p>

<p>以下は、決められた順番でアクセスしなければならないAPI4つを順に叩き、その結果を使って何か最終的に処理を行ったという想定の例です。この中で使われている<code>doAjaxStuff</code>は、<code>XMLHttpRequest</code>を使ってGETなりPOSTなりのリクエストを送る、いわゆるAjaxを行うfunctionであると想像して下さい。リクエストしたいパラメーターなり、リクエストの成功時、失敗時に実行したいfunctionを受け取れるものとします。</p>

<p></p><pre class="crayon-plain-tag">var fetchSomething1 = function(done) {
  // API1にアクセス
  doAjaxStuff(someOptions, {
    success: function(data) {
      done(); // 成功したら渡されたfunctionを実行
    }
  });
};

// fetchSomething1と同じようにそれぞれ別のAPIにアクセスするfunction群
var fetchSomething2 = function(done) { /* 省略 */ };
var fetchSomething3 = function(done) { /* 省略 */ };
var fetchSomething4 = function(done) { /* 省略 */ };

var doSomethingFinally = function() {
  // APIにアクセスして取得してきたデータを使って何かする
};

/* 順番に実行 */

fetchSomething1(function() {
  fetchSomething2(function() {
    fetchSomething3(function() {
      fetchSomething4(doSomethingFinally); // 全部終わったら doSomethingFinally()
    });
  });
});</pre><p></p>

<p>それぞれの動作はすぐに終わるものではなく、時間がかかるもの。そしてその処理が終わった時に別の処理を行わせるために今のコールバックを利用するとすると、functionの中にfunction、その中にまたfunction&#8230;と、マトリョーシカみたいな入れ子functionを作ることになってしまうことがあります。</p>

<p>コールバックの仕組みを利用する以上、仕方のないことなのですが、複雑な処理の場合、この書き方はなかなかに読みづらいものです。ここにエラー処理を加えた場合、さらにややこしくなります。第二引数にエラー時に実行させたいfunctionを指定できるようにした……というような実装をしたとすると、例えば以下の様な形になるでしょうか。</p>

<p></p><pre class="crayon-plain-tag">fetchSomething1(function() {
  fetchSomething2(function() {
    fetchSomething3(function() {
      fetchSomething4(doSomethingFinally, function() {
        // fetchSomething4のエラー処理
      });
    }, function() {
      // fetchSomething3のエラー処理
    });
  }, function() {
    // fetchSomething2のエラー処理
  });
}, function() {
  // fetchSomething1のエラー処理
});</pre><p></p>

<p>これだとどこにどのエラー処理を書けばいいのか、なかなかに解読が困難です。</p>

<p>ブラウザ上で動作させるJavaScriptの場合、APIにアクセスしたりなどするためにAjaxを利用することが多いでしょう。複雑なWebアプリケーションの場合、いくつものAPIにアクセスし、返ってきたデータ群からDOMを生成し、ページを作ったりするかもしれません。そんな時、このように複雑なコールバックの入れ子になってしまうことは珍しいことではありません。ほか、複数の非同期処理が全て完了したい時に何か処理をさせたいというケースもよくあります。時代の流れとともにとでも言いましょうか、JavaScriptには、非同期処理をより柔軟に行える機能が求められてきたと言ってしまって間違いはないでしょう。</p>

<h2>Promise!</h2>

<p>そんな時代に登場した非同期処理の救世主？が、Promiseです。Promiseを使えば、実行と完了に遅延がある処理をうまい具合に扱うことができます。いろいろと説明するよりも、コードを見ながら理解していきましょう。以下がPromiseを使った非同期処理の例です。この例では、先ほど例として挙げた、APIにアクセスするfunction <code>fetchSomething1</code>を、Promiseを使って書いてみたサンプルを例とします。</p>

<p></p><pre class="crayon-plain-tag">var fetchSomething1 = function() {
  return new Promise(function(resolve, reject) {
    // API1にアクセス
    doAjaxStuff(someOptions, {
      success: function(data) { // 成功した場合
        resolve();
      },
      fail: function() { // 何かしらエラーが発生した場合
        reject({ message: 'APIにアクセスできませんでした' });
      }
    });
  });
};

fetchSomething1().then(function() {
  alert('API1よりデータを取得しました');
}, function(error) {
  alert('API1よりデータを取得できませんでした。エラーメッセージ: ' + error.message);
});</pre><p></p>

<p>function <code>fetchSomething1</code>は、Promiseオブジェクトを作り、返します。</p>

<p>ここで何が起こっているかざっと解説してみます。</p>

<h2>Promiseオブジェクトの状態</h2>

<p>Promiseを理解するためにはまず、Promiseオブジェクトの「状態」について理解することが必要です。</p>

<p>何はともあれ、最初にすることは、Promiseオブジェクトの作成です。Promiseオブジェクトを作るには、コンストラクタである<code>Promise</code>を<code>new</code>すればよいだけです。このPromiseオブジェクトを経由し、処理がうまくいった場合、いかなかった場合の処理を続けて書くことができます。それをどう書くのかは後述するとして、まずはPromiseオブジェクトの状態についてです。</p>

<p>Promiseオブジェクトには状態があります。それは以下の3種類です。</p>

<ul>
<li><code>pending</code>: 未解決</li>
<li><code>fulfilled</code>: 無事完了した</li>
<li><code>rejected</code>: 棄却された</li>
</ul>

<p>最初は<code>pending</code>になっていますが、無事完了すると<code>fulfilled</code>、棄却されると<code>rejected</code>になります。<code>pending</code>からは、<code>fulfilled</code>、<code>rejected</code>のいずれかの状態に変化することができますが、一度状態が変化したら、それ以上状態を変化させることはできません。一方通行です。</p>

<p><img src="/wp-content/uploads/2015/09/states.png" alt="states" width="640" height="354" class="aligncenter size-full wp-image-17111" srcset="/wp-content/uploads/2015/09/states.png 640w, /wp-content/uploads/2015/09/states-300x166.png 300w, /wp-content/uploads/2015/09/states-207x114.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>コンストラクタである<code>Promise</code>には、<code>new</code>する時、functionを引数として渡します。このfunction内にPromiseがラップしたい処理を書きます。</p>

<p>このfunctionには、2つの引数を指定することができます。まずは第一引数として指定している<code>resolve</code>。これは必ず指定する必要があります。この<code>resolve</code>はfunctionで、処理結果が正常だった場合に実行させます。ここでは、APIへのアクセスに成功した時に実行させています。<code>resolve</code>を実行すると、Promiseオブジェクトの状態が<code>fulfilled</code>になります。「無事完了した」ことにするfunctionです。</p>

<p>第二引数である<code>reject</code>もfunctionですが、この<code>reject</code>は<code>resolve</code>とは逆で、処理結果がエラーであった場合に実行させます。ここではAPIへのアクセスが失敗に終わった時に実行させています。<code>reject</code>を実行すると、Promiseオブジェクトの状態が<code>rejected</code>になります。「棄却された」ことにするfunctionです。この第二引数は省略可能です。</p>

<p>このようにして、Promiseコンストラクタに渡したfunction内で、Promsieオブジェクトの状態を<code>pending</code>から<code>fulfilled</code>及び<code>rejected</code>に変化させます。</p>

<p>まとめると、以下のようになります。</p>

<ul>
<li>function <code>fetchSomething1</code>を実行すると、Promiseオブジェクトが返ってくる</li>
<li>APIへのアクセスに成功するとPromiseオブジェクトの状態が<code>pending</code>から<code>fulfilled</code>になる</li>
<li>APIへのアクセスに失敗するとPromiseオブジェクトの状態が<code>pending</code>から<code>rejected</code>になる</li>
</ul>

<p>APIへのアクセス成功可否によりPromiseオブジェクトの状態が変化しますが、このfunction <code>fetchSomething1</code>を実行した側からすれば、ただひとつのPromiseオブジェクトが返ってくるだけです。</p>

<h2>then</h2>

<p>このようにして作ったPromiseオブジェクトのメソッドを呼ぶことで、状態変化が起こった時に実行されるfunctionを登録することができます。それを行うのが<code>then</code>です。以下のように使います。</p>

<p></p><pre class="crayon-plain-tag">fetchSomething1().then(function() {
  alert('API1よりデータを取得しました');
}, function(error) {
  alert('API1よりデータを取得できませんでした。エラーメッセージ: ' + error.message);
});</pre><p></p>

<p><code>then</code>には二つの引数を渡すことができます。第一引数として渡したfunctionは、Promiseオブジェクトの状態が<code>fulfilled</code>になった時、第二引数として渡したfunctionは、Promiseオブジェクトの状態が<code>rejected</code>になった時に実行されます。<code>then</code>の第二引数は省略可能です。</p>

<p>結果として、<code>fetchSomething1</code>のメインの処理が無事完了すれば、「API1よりデータを取得しました」と、棄却されたら、「API1よりデータを取得できませんでした。エラーメッセージ: APIにアクセスできませんでした」とalertが出ます。</p>

<p>この<code>then</code>に渡したfunctionは、<code>resolve</code>及び<code>reject</code>が実行された時に渡された値を受け取ることができます。ここでは、<code>reject</code>時に渡されているオブジェクトを受け取り、エラーメッセージとして利用しています。</p>

<h2>次回に続く</h2>

<p>今回は、JavaScriptにおいて非同期処理を扱う方法と、Promiseのごく基礎的な書き方について紹介しました。今回の内容だけでは、Promiseを使って何が嬉しいのかよく分からないかもしれません。次回は、複数の非同期処理を順次処理する方法、並列に処理する方法、エラーを効率的にハンドリングする方法等を紹介していきます。</p>
]]></content:encoded>
		
		<series:name><![CDATA[ECMAScript 2015（ECMAScript 6）特集]]></series:name>
	</item>
		<item>
		<title>Babelで始める！モダンJavaScript開発</title>
		<link>/kyo_ago/16979/</link>
		<pubDate>Thu, 01 Oct 2015 00:00:56 +0000</pubDate>
		<dc:creator><![CDATA[吾郷 協]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[babel]]></category>

		<guid isPermaLink="false">/?p=16979</guid>
		<description><![CDATA[連載： ECMAScript 2015（ECMAScript 6）特集 (3)この記事は「ECMAScript2015/ES6特集」の第3回目です。この特集ではJavaScriptの次世代仕様であるECMAScript ...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/ecma2015/" class="series-336" title="ECMAScript 2015（ECMAScript 6）特集" data-wpel-link="internal">ECMAScript 2015（ECMAScript 6）特集</a> (3)</div><p>この記事は「ECMAScript2015/ES6特集」の第3回目です。この特集ではJavaScriptの次世代仕様であるECMAScript 2015（ECMAScript 6）を取り上げ、歴史や経緯から追加された機能や文法の詳細など、複数回に渡って解説していきます。</p>

<p>ここではECMAScriptの新仕様を先取りできるトランスパイラ、Babelの紹介を行います。</p>

<h1>Babelとは</h1>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/09/babel1.png" data-wpel-link="internal"><img src="/wp-content/uploads/2015/09/babel1-300x168.png" alt="babel" width="300" height="168" class="alignnone size-medium wp-image-17231" srcset="/wp-content/uploads/2015/09/babel1-300x168.png 300w, /wp-content/uploads/2015/09/babel1-207x116.png 207w, /wp-content/uploads/2015/09/babel1.png 551w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<p><a href="https://babeljs.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Babel</a>とは、2014/9から開発が始まっているECMAScriptコンパイラです。</p>

<p>機能としては、ECMAScript2015 (ES6)やECMAScript7などで書かれたソースコードを一般的なブラウザがサポートしているECMAScript5の形式に出力することができます。</p>

<p></p><pre class="crayon-plain-tag">const obj = (() =&gt; {
  return {
    method() {
      alert('Hello Babel!');
    }
  };
})();</pre><p></p>

<p></p><pre class="crayon-plain-tag">'use strict';

var obj = (function () {
  return {
    method: function method() {
      alert('Hello Babel!');
    }
  };
})();</pre><p></p>

<p>Babelは最低限の機能を<a href="http://babeljs.io/docs/advanced/caveats/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">IE8</a>以降で、フル機能をIE10以降でサポートします。<br />
（実際にはIE9以降から使用することを推奨します）</p>

<p>当初Babelは6to5と呼ばれていましたが、ECMAScript7の仕様なども取り込むようになったため、バージョンを想定しないBabelという名前に変更されました。</p>

<h1>Babelの特徴</h1>

<p>Babelと同じように「トランスパイルすることでJavaScriptのコードを出力する」ツールにはTypeScriptやCoffeeScriptなどがあります。</p>

<p>それらと比較するとBabelは「ECMAScript標準仕様をベースにしている(*)」という特徴があります。</p>

<p>(*) 実際にはJSXもサポートしているため、必ずしもECMAScript標準仕様のみをサポートしているわけではありません。</p>

<p>このため、「いずれ標準実装される仕様を先取りできる」、「Babel自体が廃れても同じような標準仕様を扱うツールがあれば乗り換えできる」といった利点があります。</p>

<h1>簡単に始める方法</h1>

<p>それでは早速Babelを使ってみましょう。</p>

<p>お手軽に始める場合、Babelの公式サイトで公開されている<a href="https://babeljs.io/repl/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">オンライン上のトランスパイルサービス</a>が便利でしょう。</p>

<p>これは左側にコードを書くとトランスパイルした結果を右側に出力してくれます。</p>

<p>もちろんこのまま開発を行うのは難しいため、実際には手元にツールをインストールして使うことになります。</p>

<h1>Babelのインストール</h1>

<p>Babelはnpm経由で以下のようにインストールします。</p>

<p><code>
$ npm install --global babel
</code></p>

<p>これで<code>babel</code>コマンドが使用できるようになりました。</p>

<h1>CLIを使った変換方法</h1>

<p>それではまずは<code>babel</code>コマンド経由で変換してみましょう。</p>

<p><code>babel</code>コマンドでは以下のようにファイル名を引数に与えるか、標準入力にソースを渡すことによって標準出力へ変換結果を出力します。</p>

<p><code>
$ cat sample.js
() =&gt; {}
$ babel sample.js
"use strict";</p>

<p>(function () {});</p>

<p>$
</code></p>

<p>この方法でも変換はできますが、実際の現場では次で紹介するような別のコマンド経由で変換されることが一般的です。</p>

<h1>gulpを使った変換方法</h1>

<p>では次に<a href="http://gulpjs.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">gulp</a>を使った変換方法を紹介します。</p>

<p>gulpを使って変換するためには、gulpとBabelを繋げるためのgulp-babelというパッケージをインストールします。</p>

<p><code>
$ npm install --global gulp
$ npm install --save-dev gulp-babel
</code></p>

<p>それでは変換してみましょう。</p>

<p>まず<code>gulpfile.js</code>に以下のように記述します。</p>

<p></p><pre class="crayon-plain-tag">var gulp = require('gulp');
var babel = require('gulp-babel');
 
gulp.task('default', function () {
    return gulp.src(['src/*.js', 'src/**/*.js'])
        .pipe(babel())
        .pipe(gulp.dest('dist'));
});</pre><p></p>

<p>この状態で<code>gulp</code>コマンドを実行することで、<code>src/</code>以下のjsファイルをBabelで変換して<code>dist</code>以下に書き出すことができます。</p>

<h1>gruntを使った変換方法</h1>

<p>次は<a href="http://gruntjs.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">grunt</a>を使った変換方法を紹介します。</p>

<p>gruntを使って変換するためには、gulpの場合と同様にgrunt-babelというパッケージをインストールします。</p>

<p><code>
$ npm install --global grunt-cli
$ npm install --save-dev grunt grunt-babel
</code></p>

<p>それでは変換してみましょう。</p>

<p><code>Gruntfile.js</code>に以下のように記述します。</p>

<p></p><pre class="crayon-plain-tag">module.exports = function(grunt) {
  grunt.initConfig({
    babel: {
      dist: {
        files: [{
          "expand": true,
          "cwd": "src/",
          "src": ["*.js", "**/*.js"],
          "dest": "dist/",
          "ext": ".js"
        }]
      }
    }
  });

  grunt.loadNpmTasks('grunt-babel');

  grunt.registerTask('default', ['babel']);
};</pre><p></p>

<p>この状態で<code>grunt</code>コマンドを実行することで、<code>src/</code>以下のjsファイルをBabelで変換して<code>dist/</code>以下に書き出すことができます。</p>

<h1>Browserifyを使った変換方法</h1>

<p>ここまではタスクランナー経由での使い方を紹介しましたが、最後に<a href="http://browserify.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Browserify</a>経由での変換方法もご紹介します。</p>

<p>Browserifyとは、以下のようにNode.jsで使える外部ライブラリを読み込むrequire構文（CommonJS）をブラウザ上でも使えるように変換するためのツールです。自動的に外部ライブラリの参照先のファイルを結合してひとつのファイルにまとめてくれます。</p>

<p></p><pre class="crayon-plain-tag">module.exports = function () {
  console.log('Hello browserify!');
};</pre><p></p>

<p></p><pre class="crayon-plain-tag">var exportsCode = require('./exports.js');
exportsCode(); // console.log('Hello browserify!');</pre><p></p>

<p>Babelは、同じように外部ライブラリを読み込むECMAScritpt2015 (ES6)のmodule構文を上記のようなrequire構文）に変換してくれますが、ひとつのファイルにまとめてくれる機能はありません。そのため、実際の実行ではエラーになってしまいます。</p>

<p></p><pre class="crayon-plain-tag">export default function () {
  console.log('Hello ES2015 exports!');
};</pre><p></p>

<p></p><pre class="crayon-plain-tag">import exportsCode from './exports.js';
exportsCode(); // console.log('Hello ES2015 exports!');</pre><p></p>

<p>これを解決するには、Babelだけでなく、Browserifyを組み合わせてrequire構文をブラウザでも実行できるようにする必要があります。これらを組み合わせた場合、ES2015のmodule構文で書いたものが、Babelによってrequire構文に変換され、require構文の（ブラウザでの）実行に必要なファイルの結合処理をBrowserifyが行う形となります。</p>

<p>このようにWebフロントエンドの開発の場合、BrowserifyとBabelはセットで使われることが多いです。</p>

<p>BrowserifyとBabelの連携方法は、単純にBabelの出力結果をBrowserifyに渡すだけでなく、Browserifyのもつプラグイン機構でBabelを呼び出すこともできます。</p>

<p>では、Browserify経由でBabelを実行するためのbabelifyというパッケージをインストールします。</p>

<p><code>
$ npm install --global browserify
$ npm install --save-dev babelify
</code></p>

<p>Browserifyはgruntやgulp経由で起動する方法もありますが、以下のようにコマンドラインからでも起動できます。</p>

<p><code>
$ browserify src/app.js -t babelify -o dist/app.js
</code></p>

<p><code>-t</code>でbabelifyを指定することで変換時にBabelを呼び出しています。</p>

<hr />

<p>ここまで変換方法を紹介してきましたが、これ以外にも<a href="https://babeljs.io/docs/setup/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">様々な方法</a>でコードを変換することができます。</p>

<p>他のツールとの親和性はBabelの大きな特徴で、さまざまなツールを使用している状態でもスムーズに導入することができます。</p>

<h1>オプション</h1>

<p>ここまで紹介してきた内容でも最低限Babelでの変換は行えますが、細かい挙動を制御する場合オプションの指定が必要になる場合があります。</p>

<p>Babelには<a href="https://babeljs.io/docs/usage/options/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">さまざまなオプションがあります</a>が、ここではその中から主要なものを取り上げて紹介します。</p>

<ul>
<li>stage</li>
</ul>

<p>BabelはECMAScript2015 (ES6), ECMAScript7をECMAScript5に変換しますが、ECMAScript2015 (ES6), ECMAScript7の仕様でもまだ議論中のものもあり、安定度はまちまちです。</p>

<p>そこで、ECMAScriptの中でもまだ議論しきれていない仕様に関しては、stageという概念を使って安定度を示しています。</p>

<p>Babelはこのstageを指定する機能を備えており、stageを指定することでまだ議論の進んでいない仕様も使うことができます。</p>

<p>各stageでどういった機能が使えるようになるかは、<a href="https://babeljs.io/docs/usage/experimental/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">こちら</a>をご覧ください。</p>

<p>初期値は2が指定されており、草案（Draft）レベルのものが使用できます。</p>

<p>基本的には初期値で構いませんが、どうしても先取りしたい仕様がある場合には仕様が変わってしまうリスクを踏まえた上で、より新しい仕様を使うこともできます。</p>

<ul>
<li>sourceMaps</li>
</ul>

<p>JavaScriptのコンパイラは性質上、元のソースコードと違った形式で出力されるため、実行時に何か問題があった場合にデバッグが困難になるという性質があります。</p>

<p>この問題に関しては標準仕様としてSourceMapという仕様が存在し、モダンブラウザではこの機能をサポートしています。</p>

<p>SourceMapを使うことで変換前のコードと変換後のコードを対応付けることができるため、実行時に問題が発生しても元のソース上でどこに問題があったのかを容易に把握することができます。</p>

<p>BabelのsourceMapsオプションはソースコードと同時にsourceMapファイルを出力することができ、trueを指定した場合変換後のソースとは別にsourceMapファイルを、&#8221;inline&#8221;を指定した場合変換後のソースファイルにsourceMapファイルを埋め込んで出力できます。</p>

<h1>オプションの指定方法</h1>

<p>さまざまなツールと連携できる点が魅力のBabelですが、連携する場合に問題になるのがBabel自体に対するオプションの指定方法です。</p>

<p>連携するツールによってはBabelに対してのオプションを指定する方法を提供している場合もありますが、場合によってはドキュメントに書かれていなかったり提供されていないこともあります。</p>

<p>そこで便利なのが設定を独立して記述できる<a href="https://babeljs.io/docs/usage/babelrc/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">.babelrc</a>ファイルです。</p>

<p>このファイルをBabelを実行するフォルダ（基本的にpackage.jsonと同じ場所）へ設置することで、連携ツール毎のオプション指定の方法を気にすることなく一括でオプションを指定することができます。</p>

<p><code>
$ cat .babelrc
{
  "stage": 1
}
</code></p>

<h1>最後に</h1>

<p>駆け足でしたがここまでBabelの紹介をしてきました。</p>

<p>Babelを使った開発はすでに一般的に行われており、公開されている製品での使用もよく見るものになっています。</p>

<p>皆様もこれまでブラウザがサポートしなければ使えなかったECMAScriptの最新仕様を、自由に使える環境での開発を是非体験してみてください。</p>
]]></content:encoded>
		
		<series:name><![CDATA[ECMAScript 2015（ECMAScript 6）特集]]></series:name>
	</item>
		<item>
		<title>ECMAScript 2015のブラウザ対応状況と実践投入に向けて</title>
		<link>/1000ch/16995/</link>
		<pubDate>Wed, 30 Sep 2015 00:00:28 +0000</pubDate>
		<dc:creator><![CDATA[泉水翔吾]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">/?p=16995</guid>
		<description><![CDATA[連載： ECMAScript 2015（ECMAScript 6）特集 (2)　この記事は「ECMAScript2015/ES6特集」の第2回目です。第1回ではECMAScriptの歴史やES2015の新機能について紹介...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/ecma2015/" class="series-336" title="ECMAScript 2015（ECMAScript 6）特集" data-wpel-link="internal">ECMAScript 2015（ECMAScript 6）特集</a> (2)</div><p>　この記事は「ECMAScript2015/ES6特集」の第2回目です。第1回ではECMAScriptの歴史やES2015の新機能について紹介しましたが、今回は各ブラウザの対応状況や、実戦投入に向けて踏まえておくべき知識を解説します。</p>

<h2>ECMAScript 2015の対応状況</h2>

<p>　ECMAScript 2015（ECMAScript 6th edition）は、2015年の6月に無事策定されました。しかし、実際にES2015の機能を使っていくには、ブラウザなどに搭載されているJavaScriptエンジンが対応していなくてはなりません。</p>

<p>　ブラウザの実装状況については<a href="http://kangax.github.io/compat-table/es6/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript 6 compatibility table</a>が参考になります。Chrome 46・Firefox 42・Edgeは既に多くの機能を実装してあり、DevToolsなどでも試すことができます。WebKitも順調に実装が進んでおり、Safari 9ではES2015の機能の大半を使えるようになる見込みです。同じV8エンジンを使っているNode.js/io.jsも、Chromeに近い対応状況と見てよいでしょう。</p>

<p><img src="/wp-content/uploads/2015/09/compat-table-640x424.png" alt="compat-table" width="640" height="424" class="alignnone size-large wp-image-16996" srcset="/wp-content/uploads/2015/09/compat-table.png 640w, /wp-content/uploads/2015/09/compat-table-300x199.png 300w, /wp-content/uploads/2015/09/compat-table-207x137.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>　各ブラウザベンダーの正確な実装状況については以下を参照してください。</p>

<ul>
<li><a href="http://www.webkit.org/status.html#specification-ES6" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">WebKit Web Platform Status</a></li>
<li><a href="https://www.chromestatus.com/features#ES6" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Chrome Platform Status</a></li>
<li><a href="https://developer.mozilla.org/en/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript 6 support in Mozilla</a></li>
<li><a href="http://dev.modern.ie/platform/status/?search=es6" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Microsoft Edge | Dev</a></li>
</ul>

<p>　Chrome・Firefox・Edgeなどのモダンブラウザのみをターゲットにする場合は、近いうちにES2015を存分に使っていけるかもしれません。しかし実際には、IE11やそれ以前のブラウザのシェアを考慮すると互換性は無視できないのが現実です。</p>

<h2>トランスパイラの利用</h2>

<p>　ブラウザが対応しないとES2015を実行できないのは事実ですが、ブラウザ対応を待っていてはいつまでもES2015を導入できません。今のうちから導入していくためには、ES2015で書かれたJavaScriptを対応していないブラウザでも実行できる形（ES5）に変換するトランスパイラを使うという手段があります。ES2015を取り入れビルドプロセスでトランスパイラを適用することで、いざサーバーから配信する際にはES5に変換、あるいはポリフィルがバンドルされた形にします。</p>

<p>　トランスパイラには今最も普及している<a href="https://babeljs.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Babel</a>やGoogleが開発する<a href="https://github.com/google/traceur-compiler" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Traceur Compiler</a>があります。</p>

<p><img src="/wp-content/uploads/2015/09/babel-640x424.png" alt="babel" width="640" height="424" class="alignnone size-large wp-image-16997" srcset="/wp-content/uploads/2015/09/babel.png 640w, /wp-content/uploads/2015/09/babel-300x199.png 300w, /wp-content/uploads/2015/09/babel-207x137.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>　BabelとTraceur CompilerはES2015のトランスパイルだけでなく、ES7以降で提案されている実験的な機能（<code>async</code>・<code>await</code>・デコレータ等…）のトランスパイルもサポートしています。更にBabelはReactで採用されているJSXなどのビルドもサポートしています。Facebookが公式で開発していた<a href="https://www.npmjs.com/package/react-tools" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">React Tools</a>は非推奨となり、Babelを使うように薦められています。</p>

<ul>
<li><a href="https://facebook.github.io/react/blog/2015/06/12/deprecating-jstransform-and-react-tools.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Deprecating JSTransform and react-tools</a></li>
</ul>

<h2>TypeScriptを使う</h2>

<p>　先日バージョン1.6がリリースされたTypeScriptでもES2015の機能を使っていくことができます。TypeScriptは、もともとJavaScriptのスーパーセットとして設計されているAltJSということもあり、ES2015の機能もどんどん取り込まれています。また、<a href="https://github.com/Microsoft/TypeScript/wiki/What&#039;s-new-in-TypeScript#typescript-16" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ReactのJSXのサポートも追加されている</a>ようなので興味のある方は試してみるとよいでしょう。</p>

<p>　プレーンなES2015とは異なり、仮に全てのブラウザがES2015の仕様を実装してもTypeScriptのビルドが前提にはなります。しかし、ソースコードに事前処理を加えることはもはや当たり前になっていますし、そうこうしているうちにES2016などの新たな仕様が登場してくることを考えれば、トランスパイラなしにES2015を書いていくのはあまり現実的ではないのかもしれません。</p>

<p>　TypeScriptでES2015を試していく方法については、わかめさんの「<a href="https://html5experts.jp/vvakame/16241/" data-wpel-link="internal">TypeScriptを使ってECMAScript 2015時代のJavaScriptを先取りしよう！</a>」という記事が大変参考になります。</p>

<h2>限定された環境で試してみる</h2>

<p>　ES2015を導入していくためには、トランスパイラの他に、実行環境を限定して取り入れていくという手段もあります。WebアプリケーションであればURLがわかれば対応・非対応に関わらずブラウザからアクセスできてしまうため、ユーザー体験を損ねる可能性があります。しかし、書いたプログラムの実行環境が限定されれば、トランスパイルを介すことなく導入していくことも可能です。</p>

<p>　ひとつはNode.js環境で使うことです。Node.jsはブラウザとは異なり、こちらで実行環境を選定できる他、NPMパッケージとして配信するモジュールでも<code>package.json</code>の<code>engines</code>属性にバージョンを指定することで、実行環境をある程度制限できます。</p>

<p></p><pre class="crayon-plain-tag">{
  "name": "node-sample-module",
  "version": "0.1.0",
  "description": "Node Sample Module",
  "license": "MIT",
  "repository": "1000ch/node-sample-module",
  "engines": {
    "node": "&gt;=0.10.0"
  },
  "scripts": {
    ...
  },
  "dependencies": {
    ...
  },
  "devDependencies": {
    ...
  }
}</pre><p></p>

<p>Node.jsはつい先日<a href="https://nodejs.org/en/blog/release/v4.1.1/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">v4.1.1がリリースされました</a>。v0.12系やiojsでも<code>--harmony</code>フラグ無しで次の機能を使うことができます。</p>

<ul>
<li>ブロックスコープ（<code>let</code>・<code>const</code>）</li>
<li><code>class</code></li>
<li>データコレクション（<code>Map</code>・<code>Set</code>・<code>WeakMap</code>・<code>WeakSet</code>）</li>
<li><code>Promise</code></li>
<li><code>Symbol</code></li>
<li>ジェネレータ関数（Generator Function）</li>
<li>テンプレート文字列（Template String）</li>
<li>etc&#8230;</li>
</ul>

<p>　なので、サーバープログラムはもちろん、NPMモジュール、あるいは<a href="http://electron.atom.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Electron</a>のアプリを書いていく中でこれらを試すのもひとつです。ES2015の機能を全て試すことができるわけではありませんが、V8の実装状況に応じて徐々に充実していくでしょう。さらに、先程紹介したBabelには、ES2015のコードも逐次コンパイルしてシームレスに実行する<code>babel-node</code>というコマンドもあります。これを使えばBabelのコンパイルでフォールバックできる機能全てを使っていくことも可能です。</p>

<p>　ChromeやFirefoxの拡張機能にES2015を使っていくのも良いでしょう。インストールされる先は必然的に限定されますし、ChromeやFirefoxは積極的にサポートを進めているので、試すには持ってこいの環境とも言えます。ES2015のどの機能を使えるかについては、前述の<a href="http://kangax.github.io/compat-table/es6/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript 6 compatibility table</a>のChromeとFirefoxがそのまま対応します。</p>

<h2>まとめ</h2>

<p>　ブラウザなどの対応状況はまだ充分とは言えませんが、仕様が策定された今、使わずに踏みとどまっているのは勿体ないと言えます。ES2015が当たり前になる未来に備えて、積極的に試していきましょう。</p>
]]></content:encoded>
		
		<series:name><![CDATA[ECMAScript 2015（ECMAScript 6）特集]]></series:name>
	</item>
		<item>
		<title>ECMAScript 2015(ES6)の概要と次世代JavaScriptの新たな機能</title>
		<link>/1000ch/16984/</link>
		<pubDate>Tue, 29 Sep 2015 00:00:00 +0000</pubDate>
		<dc:creator><![CDATA[泉水翔吾]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">/?p=16984</guid>
		<description><![CDATA[連載： ECMAScript 2015（ECMAScript 6）特集 (1)　この記事は「ECMAScript2015/ES6特集」の第1回目です。この特集ではJavaScriptの次世代仕様であるECMAScript...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/ecma2015/" class="series-336" title="ECMAScript 2015（ECMAScript 6）特集" data-wpel-link="internal">ECMAScript 2015（ECMAScript 6）特集</a> (1)</div><p>　この記事は「ECMAScript2015/ES6特集」の第1回目です。この特集ではJavaScriptの次世代仕様であるECMAScript 2015（ECMAScript 6）を取り上げ、歴史や経緯から追加された機能や文法の詳細など複数回に渡って解説していきます。</p>

<h2>ECMAScriptとJavaScript</h2>

<p>　そもそもECMAScriptとはなんでしょうか？JavaScriptとは一体何が違うのでしょうか？ECMAScriptとJavaScriptの関係は、JavaScriptが生まれた1995年まで遡ります。</p>

<p>　JavaScriptは1995年、当時Netscape CommunicationsにいたBrendan Eich氏がWebで実行できるスクリプト言語として開発しました。その後Internet Explorerに搭載されWebの普及と共に浸透していきますが、当初はブラウザベンダーによる独自の拡張が多く互換性は低いものでした。そこで、<a href="https://ja.wikipedia.org/wiki/Ecmaインターナショナル" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Ecmaインターナショナル</a>が中心となり、JavaScriptの中核仕様を抜き出して標準化したのがECMAScriptです。</p>

<p><img src="/wp-content/uploads/2015/09/ecmascript2015-640x424.png" alt="ecmascript2015" width="640" height="424" class="alignnone size-large wp-image-16992" srcset="/wp-content/uploads/2015/09/ecmascript2015.png 640w, /wp-content/uploads/2015/09/ecmascript2015-300x199.png 300w, /wp-content/uploads/2015/09/ecmascript2015-207x137.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>　つまり、ECMAScriptはJavaScriptの言語仕様であり、JavaScriptはECMAScriptの仕様に基づいた言語のひとつということになります。他のECMAScriptを実装している言語としては、ActionScriptやJScriptなどがあります。</p>

<h2>ECMAScript 2015とECMAScript 6</h2>

<p>この連載で解説していくのは、先日策定されたECMAScript（ECMA-262）の6th editionです。ECMAScript 6th editionの6を取ってECMAScript 6（ES6）と呼ばれていますが、正確な呼称をECMAScript 2015（ES2015）とし、今後は年単位のより細かいリリースを計画しているようです。</p>

<p>　以降、本記事ではES2015と統一して表記しますが、リンク先がES6になっていたりすることもあります。</p>

<h2>ES2015に追加される仕様</h2>

<p>　ES2015には、非力であったこれまでのJavaScriptに対して文法や機能が多く追加されており、より安全で便利なプログラム言語に進化しています。ES2015の仕様は公式ホームページに掲載されていますのでチェックしてみましょう。</p>

<ul>
<li><a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript® 2015 6th edition (June 2015) PDF</a></li>
<li><a href="http://www.ecma-international.org/ecma-262/6.0/index.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript® 2015 6th edition (June 2015) HTML</a></li>
</ul>

<p>　ES2015から追加された機能を確認するには次のリソースが参考になります。特に後者は、ES6の機能とそれをES5以前で実装した場合にどうなるかのサンプルが比較されており、とても参考になります。</p>

<ul>
<li><a href="http://git.io/es6features" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript 6</a></li>
<li><a href="http://es6-features.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript 6 — New Features: Overview &amp; Comparison</a></li>
</ul>

<p>　今回はこの中から主な新機能を、シンタックスとオブジェクトの2つに分けて紹介していきますので、「ES5でこのように書いていたものが、ES2015ならこう書ける！」というのを感じてもらえればと思います。</p>

<h2>ES2015の新たなシンタックス</h2>

<p>　ES2015には、変数や関数の宣言・変数の代入・引数の展開・ジェネレータ関数など、実に多くの新しい文法が追加されています。</p>

<ul>
<li><code>let</code>・<code>const</code>キーワードによる変数宣言</li>
<li><code>class</code>キーワードによるクラス宣言</li>
<li>関数の引数のデフォルトパラメータ（Default Parameters）</li>
<li>関数の可変長引数（Rest Parameters）</li>
<li>アロー関数（Arrow Functions）</li>
<li>ジェネレータ関数（Generator Functions）</li>
<li>配列展開（Array Spread）</li>
<li>分割代入（Destructing Assignment）</li>
<li>文字列のテンプレートリテラル（Template Strings）</li>
<li><code>import</code>と<code>export</code>によるモジュール構文（Module）</li>
</ul>

<h3>letとconstによる変数宣言</h3>

<p>　ES5以前のJavaScriptには関数スコープしか存在せず、馴染みの深い<code>var</code>による宣言はしばし事故を招き、関数スコープを利用するために、無名関数を使ったスコープ作成の記述を用いることがしばしばありました。これに対し、<code>let</code>や<code>const</code>による変数宣言ではブラケット<code>{}</code>によるブロックスコープが有効になります。</p>

<p></p><pre class="crayon-plain-tag">let foo = [1, 2, 3];
{
  let foo = [4, 5, 6];
  console.log(foo);
  // =&gt; 4, 5, 6
}
console.log(foo);
// =&gt; 1, 2, 3</pre><p></p>

<p>　<code>const</code>は定数を宣言したいときに使うキーワードであり、宣言された変数には、宣言時を除いて値の代入が不可能であるという性質を持ちます。<code>var</code>によって宣言した変数は命名などで工夫していても常に値が書き換わるリスクを孕んでいます。しかし<code>const</code>で宣言された定数に値を再代入しようとすると、例外が発生しプログラムの実行はストップし、値の不変性がプログラムレベルで保証されます。</p>

<p></p><pre class="crayon-plain-tag">{
  const PI = 3.14;
  const circleArea = function (radius) {
    return radius * radius * PI;
  };
  console.log(circleArea(3));
  // =&gt; 28.26

  // PI = 3.1415;のような再代入はできない
}
console.log(PI);
// =&gt; undefined</pre><p></p>

<h3>classによるクラス構文</h3>

<p>　JavaScriptでnewを伴うオブジェクトの作成をするには、以下のように関数を宣言することで「クラスのようなもの」を実現してきました。このES5を使ったクラス表現はnewを使わずとも関数として呼び出すことが可能であるため、グローバル変数を書き換えてしまうリスクを常にはらんでいます。これをES2015のclassを使って書き直してみます。</p>

<p></p><pre class="crayon-plain-tag">// これまでのクラスのようなもの
function Human(name) {
  this.name = name;
}

Human.prototype.hello = function () {
  console.log('My name is ' + this.name);
};

// ES2015のclassを使って書き直す
class Human {
  constructor(name) {
    this.name = name;
  }
  hello() {
    console.log('My name is ' + this.name);
  }
}</pre><p></p>

<p>　ES2015の<code>class</code>を使って宣言された<code>Human</code>は<code>new</code>キーワードなしで使うことはできないので、より副作用がない形でクラスを宣言可能になっています。</p>

<h3>アロー関数による関数宣言</h3>

<p>　<code>function</code>を使った関数の定義に加えて、ES2015からはアロー関数が使えるようになります。<code>function</code>というキーワードを使わずに=&gt;を使って宣言することが可能になります。さらに、関数本体が単一式である場合はブラケット<code>{}</code>と<code>return</code>も省略できます。</p>

<p></p><pre class="crayon-plain-tag">// 従来のfunctionを使った書き方
let plus = function(x, y) {
  return x + y;
};

// アロー関数でfunctionを省く
let plus = (x, y) =&gt; {
  return x + y;
};

// 単一式の場合はブラケットやreturnを省略できる
let plus = (x, y) =&gt; x + y;</pre><p></p>

<p>　<code>function</code>が省略可能になることでよりシンプルに書けますが、アロー関数は宣言しているスコープの<code>this</code>を引き継ぐという特徴があります。もちろんこの機能も魅力のひとつですが、気にせずに使っていると思わぬミスをしてしまうかもしれません。</p>

<p></p><pre class="crayon-plain-tag">// ブラウザのグローバル空間に於いて以下を実行すると
// グローバルのthisであるwindowがアロー関数内のthisになる
window.setTimeout(e =&gt; {
  console.log(this === window); // =&gt; true
}, 1000);</pre><p></p>

<h2>ES2015に追加されるオブジェクト</h2>

<p>　シンタックス以外にも、様々な機能を備えたオブジェクトが追加されます。新たに追加されるオブジェクトの他にも、ArrayやObjectといった既存のオブジェクトに対して様々な関数が追加されており、機能が強化されています。</p>

<ul>
<li><code>Promise</code>: 非同期処理を抽象化するデザインパターン</li>
<li><code>Symbol</code>: ユニークな値を表現する新たなプリミティブ型</li>
<li><code>Reflect</code> / <code>Proxy</code>: オペレーションに処理を介入させる機能</li>
<li><code>Set</code> / <code>WeakSet</code>: 一意なデータスタックを表すオブジェクト</li>
<li><code>Map</code> / <code>WeakMap</code>: Key-Valueのデータ構造を表すオブジェクト</li>
</ul>

<h3>Promise</h3>

<p>　Promiseは既にお馴染みの人も多いでしょう。JavaScriptのコールバック地獄に対する解決策のひとつとしてJavaScriptの世界に持ち込まれたPromiseは、需要も高くライブラリ実装も多かったですがES2015からはついにネイティブに組み込まれます。</p>

<p></p><pre class="crayon-plain-tag">// ES5
asyncFunc1(function () {
  asyncFunc2(function () {
    asyncFunc3(function () {
      // asyncFunc1 → asyncFunc2 → asyncFunc3
      // という実行順をコールバックの入れ子で実現する
    });
  });
});

// Promiseを使ってコールバックの入れ子を避ける
// asyncFuncはそれぞれがPromiseオブジェクトを返却している
asyncFunc1().then(function () {
  return asyncFunc2();
}).then(function () {
  return asyncFunc3();
});</pre><p></p>

<p>　最近ではService WorkerやFetchなどの様々なブラウザAPIがPromiseベースで設計されており、今後もPromiseは多く使われていくでしょう。今のうちにマスターしておきたいところです。</p>

<h3>Symbol</h3>

<p>　Symbolはユニークな値を表現するプリミティブな新しい型です。Symbol型の値はStringのようにプロパティのキーとして使うことができますが、文字列とは異なりSymbolのインスタンスを使わないと参照することができません。</p>

<p></p><pre class="crayon-plain-tag">const key1 = Symbol('foo');
let object = {};
object[key1] = 'Value for key1';

console.log(object['foo']); // =&gt; undefined
console.log(object[key1]); // =&gt; Value for key1</pre><p></p>

<h3>ProxyとReflect</h3>

<p>　Proxyはオブジェクトへのアクセス時に処理を割り込ませる機能を提供するオブジェクトです。Proxyを使うと、値の参照時（get）や代入時（set）、プロパティの削除時などのタイミングで処理を介入させることが可能です。</p>

<p></p><pre class="crayon-plain-tag">let person = {
  name: '1000ch'
};

let proxied = new Proxy(person, {
  get: (target, name, receiver) =&gt; `${name} is ${target[name]}`,
  set: (target, name, value, receiver) =&gt; {
    console.log(name + ' is changed.');
    Reflect.set(target, name, value, receiver);
  }
});

console.log(proxied.name); // =&gt; name is 1000ch</pre><p></p>

<p>　<code>Proxy</code>を使ってインターセプトすると、デフォルトの振る舞いを邪魔することになります。そこで、デフォルトの挙動を再現するために<code>Reflect</code>というオブジェクトがあります。<code>Reflect</code>にはインターセプトできるハンドラ（ここでいう<code>get</code>や<code>set</code>）に対応したメソッドが用意されているので、それを呼び出してやることでデフォルトの挙動を再現することができます。</p>

<h3>MapとSet、WeakMapとWeakSet</h3>

<p>　<code>Set</code>と<code>Map</code>は、これまで配列やオブジェクトを使って表現していたデータスタックやKey-Valueといったデータ構造化をサポートします。Setのインスタンスには同一の値を追加できず、ユニークな値がスタックされていることが保証されます。MapはObjectのようにキーとそれに対する値を保持しますが、Objectと異なるのはキーに文字列以外のオブジェクトを指定できる点です。これによって様々なオブジェクトに対して値を関連付けることができます。</p>

<p></p><pre class="crayon-plain-tag">let map = new Map();
let set = new Set();

let object = {};
let array = [];

set.add(object);
set.add(array);
set.add(window);
set.add(window); // =&gt; 追加されない
set.has(window); // =&gt; true
set.delete(window);
set.has(window); // =&gt; false

map.set(object, 100);
map.set(array, 'Value for Array');
map.set(window, {});
map.get(array); // =&gt; Value for Array
map.has(object); // =&gt; true
map.delete(window);
map.get(window); // =&gt; undefined</pre><p></p>

<p>　<code>WeakSet</code>と<code>WeakMap</code>はその名の通り、弱い<code>Set</code>と<code>Map</code>です。<code>Set</code>と<code>Map</code>に比べて参照が弱くなっており、値への参照が存在しなくなるとエントリが自動で削除されるという特徴があります。例えばDOMのオブジェクトに対してWeakMapを使って値を関連付けます。そこでキーに指定したDOMオブジェクトを削除すると、関連付けた値を参照する手段はなくなるため関連付けたKey-Valueのエントリは自動で削除されるのです。Objectで表現していた場合はどこからも参照されないエントリが残ることになるのでメモリリークの要因になりますが、WeakMapを使うことでそのリスクを減らしていけるでしょう。</p>

<h2>まとめ</h2>

<p>　第一回ではECMAScriptとJavaScriptの歴史、ES2015に追加される機能の概要、主な機能の紹介をしました。次回は各ブラウザの実装状況や、実践導入に向けて抑えておくべき知識などを解説していきます。</p>
]]></content:encoded>
		
		<series:name><![CDATA[ECMAScript 2015（ECMAScript 6）特集]]></series:name>
	</item>
		<item>
		<title>TypeScriptを使ってECMAScript 2015時代のJavaScriptを先取りしよう！</title>
		<link>/vvakame/16241/</link>
		<pubDate>Wed, 29 Jul 2015 03:00:19 +0000</pubDate>
		<dc:creator><![CDATA[わかめまさひろ]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[TypeScript]]></category>

		<guid isPermaLink="false">/?p=16241</guid>
		<description><![CDATA[連載： TypeScriptでECMAScript 2015時代のJavaScriptを先取りしよう！ (1)わかめです。これから、TypeScriptを使ってECMAScript 2015スタイルのコードを書く方法を紹...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/ts-es2015/" class="series-312" title="TypeScriptでECMAScript 2015時代のJavaScriptを先取りしよう！" data-wpel-link="internal">TypeScriptでECMAScript 2015時代のJavaScriptを先取りしよう！</a> (1)</div><p>わかめです。これから、TypeScriptを使ってECMAScript 2015スタイルのコードを書く方法を紹介します。連載の初回となる本稿では、ECMAScript 2015やTypeScriptの魅力について、TypeScript用エディタの案内をしていきます。</p>

<h2>TypeScriptとは？</h2>

<p>TypeScriptはMicrosoft社が開発しているAltJSの1つです。AltJSとは、ある言語Xから、JavaScriptへと変換（トランスパイル）して使う言語の総称です。Typeという名の通り、JavaScriptの世界に静的な型付けを持込み、JavaやC#のようにコンパイル時に整合性のチェックを行うことができるようにしたものです。</p>

<p>見事チェックにパスしたら、TypeScriptからJavaScriptへと変換され、JavaScriptとして実行できる、という按配です。</p>

<p>TypeScriptは全くの新言語、というわけではありません。ECMAScript 5のsupersetとして設計されているため、皆さんが慣れ親しんだJavaScriptの構文に少しの+αを加えた言語がTypeScriptです。ECMAScript 5のsupersetなのですが、設計当初よりクラスなどのECMAScript 2015の要素も含んでいました。ゆくゆくはECMAScript 2015のsupersetにもなっていくことでしょう。</p>

<p>また、多くのECMAScript 2015用の構文をECMAScript 5の構文に変換して出力することができるため、現在のECMAScript 5をサポートしている（つまりほとんどの）ブラウザで動作させることが可能です。ECMAScript 5を改良すべく生まれたECMAScript 2015の仕様を先取りし、既存のブラウザ上で使いはじめることができる環境として、TypeScriptは魅力的でしょう。</p>

<p>TypeScriptのECMAScript 5の範囲での説明は、<a href="http://typescript.ninja/typescript-in-definitelyland/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">型の国のTypeScript</a>などを参照してください。</p>

<h2>TypeScriptとECMAScript 2015</h2>

<p>ECMAScriptというのは、JavaScriptの仕様の元になる仕様です。現在、多くのブラウザではECMAScript 5の仕様にもとづき実装が行われています。2015/06/18にECMAScript 6th editionとして、<a href="http://www.ecma-international.org/ecma-262/6.0/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript 2015が策定</a>されました。ECMAScript 2015という名前よりも、ECMAScript 6や、もっと縮めてES6という名前のほうが目にする機会が多いかもしれません。</p>

<p>これにより、今後ブラウザでのECMAScript 2015のサポートの進みが早くなっていくものと考えられます。現在の各ブラウザでのES6の機能の実装状況は<a href="https://kangax.github.io/compat-table/es6/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">es6 compat table</a>で確認するのが便利でしょう。</p>

<p>ECMAScript 2015には、言語仕様に素敵な要素が多く追加されています。いくつかを確認していきましょう。コード例を見て、「え、これ今までできなかったの？」と思ってしまうかもしれません。TypeScriptなら、今使えます。</p>

<ul>
<li>letでブロックスコープ</li>
</ul>

<p></p><pre class="crayon-plain-tag">let str = "外側の変数";
console.log(str); // 外側の変数 と表示される
{
  let str = "内側の変数"; // このブロックでだけ有効
  console.log(str); // 内側の変数 と表示される
}
console.log(str); // 外側の変数 と表示される！戻ってる！</pre><p></p>

<ul>
<li>constも使える</li>
</ul>

<p></p><pre class="crayon-plain-tag">const str = "test";
str = "re-assignment"; // 仕様上SyntaxErrorになる。ブラウザによっては未実装で単に無視される。</pre><p></p>

<ul>
<li>prototypeの代わりにclass構文！</li>
</ul>

<p></p><pre class="crayon-plain-tag">class SampleA {
  constructor() {
    this.name = "vvakame";
  }

  hi() {
    console.log("Hi! " + this.name);
  }
}

// 上記と等価なECMAScript 5なコード
function SampleB() {
  this.name = "vvakame";
}
Object.defineProperty(SampleB.prototype, "hi", {
  enumerable: false,
  configurable: true,
  writable: true,
  value: function () {
    console.log("Hi! " + this.name);
  }
});

// 実行結果は同じ
new SampleA().hi();
new SampleB().hi();</pre><p></p>

<ul>
<li>アロー関数でわかりやすいthisの振る舞い</li>
</ul>

<p></p><pre class="crayon-plain-tag">"use strict";

function Sample() {
  // this.name を設定する
  this.name = "vvakame";

  // 普通の関数とアロー関数で this の値を比べてみよう！
  var func1 = function() {
    console.log("func1: " + JSON.stringify(this));
  };
  var func2 = () =&gt; {
    console.log("func2: " + JSON.stringify(this));
  };

  // func1: undefined と表示される
  // 非直感的。いやわかるでしょ？という人はJavaScript慣れしています！
  func1();

  // func2: {"name":"vvakame"} と表示される
  // 直感的！
  func2();
}

new Sample();</pre><p></p>

<ul>
<li>デフォルトパラメータ、便利です</li>
</ul>

<p></p><pre class="crayon-plain-tag">function hello(word = "ECMAScript 2015") {
  // word が指定されなかった場合のデフォルト値を指定できる
  console.log("Hello, " + word + "!");
}
hello("JavaScript"); // Hello, JavaScript! と表示される
hello();             // Hello, ECMAScript 2015! と表示される</pre><p></p>

<ul>
<li>文字列連結もお手軽に！</li>
</ul>

<p></p><pre class="crayon-plain-tag">let name = "vvakame";
let like = "cat";

console.log(`${name} ♥ ${like}`); // vvakame ♥ cat と表示される</pre><p></p>

<h2>なぜTypeScriptか？</h2>

<p>さて、本記事ではタイトルの通り、TypeScriptを推していくわけですが、他の選択肢についても言及していきます。読者自身が何をほしいか、どうやって自由自在にコードを書きたいか、作りたいものがどれくらいの規模なのか、それぞれをよく考えて適切な選択をしていただけるといいなと考えています。もちろん、おすすめはTypeScriptですが、読者層別におすすめのツールを取り上げていきます。</p>

<h3>Babel</h3>

<p><a href="https://babeljs.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Babel</a>は旧名が6to5と呼ばれていたツールで、<a href="https://github.com/sebmck" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">sebmck</a>氏によって開発されています。Babelはソースコードのコンパイルが必要なツールで、通常foo.es6というファイルをfoo.jsに変換します。</p>

<p>現在ECMAScript 2015や、さらに次のECMAScript 7でコードを書くには一番進んでいて、将来のブラウザでもそのまま動く可能性が高いと言えます。現在のJavaScript(ECMAScript 5)に言語としての不満がない人や、Ruby on Railsなどの動的型付けの言語+フレームワークで十分に開発できている人に向いているでしょう。</p>

<p><a href="http://goo.gl/7pWFB9" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playground</a>も用意されているため、まずはブラウザ上で試してみるとよいでしょう。</p>

<h3>Flow</h3>

<p><a href="http://flowtype.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Flow</a>はFacebookが開発しているツールで、JavaScriptに対して静的な型チェックを提供します。Flow自体の開発言語はOCamlです。Flowの型チェックは、型推論や段階的な型付けを前面に押し出しているようです。JavaScriptのコード自体、関数や変数のユースケースから型を推論させることや、TypeScriptと同様に手で型の指定を記述することもできます。制作元が同じだけあって、FacebookのReactと組み合わせて利用することも考慮されているようです。</p>

<p>もし、Reactを使うようであれば、利用を検討してみてもいいかもしれません。</p>

<h3>TypeScript</h3>

<p>さて、最後に我らがTypeScriptです。<a href="http://www.typescriptlang.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TypeScript</a>は、Microsoftが3年近く前から開発し続けているツールです。TypeScriptはソースコードのコンパイルが必要なツールで、通常foo.tsというファイルをfoo.jsに変換します。</p>

<p>TypeScriptは静的型付けの言語で、コンパイル時に多くの整合性のチェックを行うことができます。例えば「Personクラスには必ずnameプロパティがある」とか「mapメソッドは第一引数に関数を取る」などがソースコードの字面上から解析できれば、それに違反している（つまりは間違った）コードを実行するよりも前の段階で検出することができます。これは、JavaやC#といった言語と同じ性質であると言えます。</p>

<p>反対に、静的型付けではない、動的型付けである言語はJavaScriptやRubyなどです。これらの言語は実行時に必要なプロパティやメソッドなどが存在していればよい、という態度です。静的・動的な型付けのどちらが優れているということはありませんが、その言語を使う個人や組織毎に得手・不得手があるでしょう。</p>

<p>別な切り口として、IDEやエディタをどの程度使っているかも検討材料になります。静的型付けの言語では実行せずともどういうプロパティやメソッドがあるかがわかります。そのため、IDEによる強力な支援が得られやすいのです。</p>

<p>例えば、<code>str.</code>と打った時に利用可能なメソッドの一覧が提示されたり、変数やメソッドのリネームが一発でできたり、関数の参照元を全てリストアップするなどの作業を行うことができます。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/07/vsc11.gif" data-wpel-link="internal"><img src="/wp-content/uploads/2015/07/vsc11.gif" alt="VisualStudioCodeによるコード補完の様子" width="600" height="450" class="alignnone size-medium wp-image-16341" /></a></p>

<p>反対に、動的にメソッドが増えたりする言語では正確なサジェストを行うのが大変難しいです。例えば、RubyのActiveRecord（ORマッパライブラリ）では、DBのテーブルのカラムに合わせて利用可能なメソッドが増えたりします。便利といえば便利ですが、IDEがライブラリのすること全てを把握してプログラムとして実行することなく呼び出し可能なメソッドの一覧を正しく提示することは現実としては不可能でしょう。</p>

<p>静的型付けな言語ではコンパイル時に検査されるおかげで、リファクタリングも抜け漏れなくできているという勇気が持てます。JavaScriptを書いている時に「テストを書き足りていないのではないか」「実行時にundefinedなプロパティを触ってしまいエラーになるのではないか」という恐怖を感じたことはありませんか？TypeScriptではこの恐怖をかなり減じ、勇気あるリファクタリングを行うことができます。常にきれいなコードを保つ足がかりをTypeScriptは提供してくれるのです。</p>

<p><a href="http://goo.gl/cC60Pk" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playground</a>も用意されているため、まずはブラウザ上で試してみると良いでしょう。</p>

<p>なお、WebComponentsが流行ったほうが、Reactが主流の未来より僕は楽だよ派の筆者としては遺憾なのですが、TypeScript 1.6でJSXサポートが入る予定です。</p>

<h2>エディタの紹介</h2>

<p>TypeScriptはコンパイラ自身にLanguage Serviceという、まさにエディタのためのような機能が組み込まれています。TypeScriptを開発するための総本山（なにせMicrosoft製ですからね）であるVisual StudioでもこのLanguage Serviceから得た情報を元に処理しています。つまり、TypeScriptでは数多くのエディタでVisual Studio相当の入力補完や、フォーマットなどが得られるようになっているのです。</p>

<p>いくつか、箇条書きで紹介していきます。</p>

<ul>
<li><a href="https://www.microsoft.com/ja-jp/dev/default.aspx" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Visual Studio</a><br>MicrosoftのIDEの最有力候補。NuGetなど独自の生態系があるが最近だいぶOSS側に歩み寄ってきた。残念ながらWindowsでしか動かない。<br><br></li>
<li><a href="https://www.visualstudio.com/ja-jp/products/code-vs.aspx" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Visual Studio Code</a> <br>最近新登場したIDE。Windows, Mac, Linuxで動作する。Previewなだけあってまだまだ機能が足りないが十分動く。Macユーザである筆者のメイン環境その1。余談だが、内部的にGitHub社製Atomが使っているElectronというフレームワークを使っていて、IDE全体がHTML+JavaScriptで作られている。<br><br></li>
<li><a href="https://atom.io/packages/atom-typescript" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">atom-typescript</a> <br>GitHub社製の<a href="http://blog.atom.io/2015/06/25/atom-1-0.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Atom</a>エディタ用のプラグイン。筆者のメイン環境その2。<br><br></li>
<li><a href="https://github.com/palantir/eclipse-typescript" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">eclipse-typescript</a> <br>Eclipse用プラグイン。かなり長期間開発が継続されている。Eclipseユーザなら検討の価値があるかも。<br><br></li>
<li><a href="http://typecsdev.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TypEcs</a><br>Eclipse用プラグイン。同上。<br><br></li>
<li><a href="https://github.com/clausreinke/typescript-tools" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">typescript-tools</a> <br>エディタそのものではないが、TypeScriptのLanguage Serviceをツール化したもの。vimやemacs、Sublime Text 3用のプラグインから利用されている。<br><br></li>
<li><a href="https://www.jetbrains.com/webstorm/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">WebStorm</a> <br>JetBrains社製のIDE。IntelliJ IDEAやPyCharm, PhpStormの仲間。ここに書いたが、WebStorm 10の時点ではLanguage Serviceを使っておらず、独自に解析しているためTypeScript用という観点で見た時は一歩劣る。筆者の旧メイン環境。</li>
</ul>

<h2>まとめ</h2>

<p>TypeScriptの環境を作り、しばらくコードを書いてみて、あまりに窮屈すぎる！エディタの恩恵を感じない！と思ったらbabelを使ってみるとよいでしょう。</p>

<p>次回は開発環境の構築と、TypeScriptを取り巻く周辺ツールについて解説します。</p>
]]></content:encoded>
		
		<series:name><![CDATA[TypeScriptでECMAScript 2015時代のJavaScriptを先取りしよう！]]></series:name>
	</item>
		<item>
		<title>「進化を続ける JavaScript ～次世代言語のステキな機能と高速化の行方～」HTML5 Conference 2013 セッションレポート</title>
		<link>/yosssi/3572/</link>
		<pubDate>Fri, 13 Dec 2013 01:00:13 +0000</pubDate>
		<dc:creator><![CDATA[吉田 啓二]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[ECMAScript 6th]]></category>
		<category><![CDATA[HTML5 Conference 2013]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[asm.js]]></category>

		<guid isPermaLink="false">/?p=3572</guid>
		<description><![CDATA[連載： HTML5 Conference 2013レポート (2)2013年11月30日（土）に開催された「HTML5 Conference 2013」の、Mozilla Japan浅井智也さんによるセッション「進化を続...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/html5-conference-2013-2/" class="series-160" title="HTML5 Conference 2013レポート" data-wpel-link="internal">HTML5 Conference 2013レポート</a> (2)</div><p>2013年11月30日（土）に開催された「<a href="http://events.html5j.org/conference/2013/11/" title="HTML5 Conference 2013" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTML5 Conference 2013</a>」の、Mozilla Japan浅井智也さんによるセッション「進化を続ける JavaScript ～次世代言語のステキな機能と高速化の行方～」のセッション内容をご紹介します。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2013/12/html5conference-report-javascript-01.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/html5conference-report-javascript-01-1024x569.png" alt="html5conference-report-javascript-01" width="1024" height="569" class="aligncenter size-large wp-image-3574" srcset="/wp-content/uploads/2013/12/html5conference-report-javascript-01-1024x569.png 1024w, /wp-content/uploads/2013/12/html5conference-report-javascript-01-300x166.png 300w, /wp-content/uploads/2013/12/html5conference-report-javascript-01-207x114.png 207w, /wp-content/uploads/2013/12/html5conference-report-javascript-01.png 640w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>

<h2>JavaScriptの課題と改良への動き</h2>

<p>現在のJavaScriptには、次のような課題があります。</p>

<ul>
<li>高速化がなかなかできない</li>
<li>クラス、モジュールがない</li>
<li>プロトタイプベースであるため、普段Javaなどでクラスを使っている人にとって、メソッド定義や継承がわかりにくい</li>
<li>メソッドとして呼び出したときはthisがそのメソッドのオブジェクトになるが、間違って関数として呼び出すとthisがwindowオブジェクトになるなど、thisの挙動を捉えるのが難しい</li>
<li>argumentsなど、ArrayのようでArrayでなくついarguments.slice()とかしてエラー原因になる、紛らわしいオブジェクトがある</li>
<li>コールバック地獄</li>
<li>実行時エラーが多く、コンパイルエラーが少ないので、デバッグが非常に大変である</li>
</ul>

<p>JavaScriptの歴史について詳しくは<a href="http://www.slideshare.net/dynamis/javascriptnext-returns" title="http://www.slideshare.net/dynamis/javascriptnext-returns" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">過去の講演資料</a>をご覧ください。簡単に言えば次の資料の通りです。次期ECMAScript 6thでは大きく改定されるため、この改定内容はぜひ知っておく必要があります。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2013/12/javascript2013-131130030521-phpapp01-page13.jpg" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/javascript2013-131130030521-phpapp01-page13.jpg" alt="javascript2013-131130030521-phpapp01-page13" width="520" height="390" class="aligncenter size-full wp-image-3578" style="border: 1px solid #000000" /></a></p>

<h2>ECMAScript 6thの概要</h2>

<h3>目標</h3>

<p>ECMAScript 6thの目標は、より開発・テストを行いやすくし、相互運用性を確保し、静的検証（コンパイルエラーの検出）を行える構文・言語仕様を提供することにあります。</p>

<h3>実装・対応状況</h3>

<p>FirefoxのSpiderMonkeyの実装範囲が比較的広く、V8がそれに続く状況になっています。機能によってはV8の方が先に入っていたり、上手く実装されているものもあります。IEは非常に安定した、広く使われている仕様が実装されており、加えて、グローバリゼーション、国際化といったビジネス系の仕様が積極的に提案、実装されています。TypeScriptは、対応範囲がクラスなどに絞られている印象があるのですが、比較的綺麗なコードが生成されます。その他にも、letやconstといったブロックスコープだけを使いたいのでしたらdefs.jsを、あるいはModuleのimport/export機能だけを使いたい場合はes6-module-loaderといったコンパイラも使うことができます。</p>

<h2>Syntax Sugar</h2>

<h3>分割代入 (Destructuring)</h3>

<p>これまでのJavaScriptでは代入文の左辺に変数を一つしか指定できませんでしたが、ECMAScript 6thでは左辺に配列やオブジェクトを指定することができるようになります。これにより、例えば、関数から配列やオブジェクトなどで複数の返り値を受け取り、それをそのまま変数に格納するといった処理を記述できるようになります。JSONから特定のデータを抜き出す、といったことを行うこともできます。</p>

<p></p><pre class="crayon-plain-tag">// 配列で受け取るサンプル: // 値の入れ替え
[a, b] = [b, a];

// 関数から複数の値を返して一気に変数に代入
var [c,d] = (function f() { return [1,2]; })(); // -&gt; c=1, d=2

// 一部省略や入れ子も可能
var [e,,[x,y]] = (function f(){
  return [3,4,[10,20]]
})();

// オブジェクトで受け取るサンプル
var fx={ name:"Firefox", vendor:"Mozilla", ver:26 };
var ch={ name:"Chrome", vendor:"Google", ver:31 };
var browsers={ firefox: fx, chrome: ch }

// 欲しいプロパティだけ一括代入
var { name: n, ver: v } = fx;
// -&gt; n="Firefox", v=26

// 関数の引数から必要なプロパティだけ受け取る
(function ({ vendor: ven }) {
  console.log(ven);
})(fx); // -&gt; "Mozilla"</pre><p></p>

<h3>default &amp; rest parameter</h3>

<p>引数のデフォルト値を設定できたり（default parameter）、関数の残りの引数を配列で受け取ったり（rest parameter）することができます。</p>

<p></p><pre class="crayon-plain-tag">e = document.body; // 何か適当な要素
function setBackgroundColor(element, color='orange') {
  element.style.backgroundColor = color;
}
setBackgroundColor(e); // オレンジに
setBackgroundColor(e, 'blue'); // 青に
setBackgroundColor(e, undefined); // オレンジに

// デフォルト値は呼び出し毎に生成される
// 同一オブジェクトが渡される Python などとは違う
function getObject(o={}) { return o; }
getObject() == getObject() // -&gt; false</pre><p></p>

<p></p><pre class="crayon-plain-tag">￼function f(a, b, ...args) { return args; }
f("IE", "Chrome"); // -&gt; []
f("IE", "Chrome", "Firefox"); // -&gt; ["Firefox"] !

// rest arguments は Array のメソッドが使える
// [].slice.call(arguments) ハックとか不要に
function sortRestArgs(...theArgs) {
  var sortedArgs = theArgs.sort();
  return sortedArgs;
}</pre><p></p>

<h3>配列の内包表記 (Comprehensions)</h3>

<p>for&#8230;ofなどを使って、直接、配列のリテラルを生成することができます。</p>

<p></p><pre class="crayon-plain-tag">// 配列のフィルタとマップ
[for (x of [1,-4,5,3,-7]) if (x &gt; 0) x] // -&gt; [1, 5, 3]
// ES5 なら次のように書く
// [1,-4,5,3,-7].filter(function(x) { return x &gt; 0 });
[for (x of [2,4,6]) x*x] // -&gt; [4, 16, 36]
// ES5 なら次のように書く:
// [2,4,6].map(function (x) { return x*x });

// 配列のデカルト積やラベル生成もシンプルに
[for (i of [0,2,4]) for (j of [5,3]) i*j]
// -&gt; [0, 0, 10, 6, 20, 12]
[for (x of 'abc'.split(''))
 for (y of '123'.split('')) (x+y)];
// -&gt; ["a1","a2","a3","b1","b2","b3","c1","c2","c3"]</pre><p></p>

<h2>Modularity</h2>

<h3>ブロックスコープ (let, const)</h3>

<p>今までのJavaScriptにはブロックスコープがなく、グローバルスコープと関数スコープしかありませんでした。変数をブロックスコープに納めるために、今まではわざわざ関数を作らなければなりませんでしたが、ECMAScript 6thでは、let, constを指定するだけでブロックスコープ変数を作成することができます。</p>

<p></p><pre class="crayon-plain-tag">{
  // let 定義: ブロックスコープ
  let a = 1, b = 10;
  // let 式・文: let (...) に続く式・文中だけで有効
  let (a = 100, c = 300) console.log(a); // -&gt; 100
  // for 文などでの let
  for (let a=0; a&lt;3; a++) {
    console.log(a+b); // -&gt; 10, 11, 12
  }
  console.log(a); // -&gt; 1
}
console.log(a); // × ReferenceError: a is not defined</pre><p></p>

<p></p><pre class="crayon-plain-tag">// 不変定数を定義
const browser = "Firefox";

// 再定義は TypeError となる
const browser = "Internet Explorer";
// TypeError: redeclaration of const browser !

// 定数への代入は単に無視される
browser = "Chrome";
console.log(browser); // -&gt; "Firefox"</pre><p></p>

<h3>Class</h3>

<p>待望のClassが使えるようになります。他のオブジェクト指向の言語と同じような形式でClassを記述することができます。constructorメソッドが初期化時の処理として使われます。</p>

<p></p><pre class="crayon-plain-tag">// クラスベース OOP でよく見る感じ
class Animal {
  constructor(name) {
    this.name = name;
    this.hungry = true;
  }
  eat() {
    this.hungry = false;
  }
  run() {
    this.hungry = true;
  }
}

// 派生クラスの定義がシンプル
class LesserPanda extends Animal {
  constructor(name, tail) {
    super(name);
    this.tail = tail;
  }
}</pre><p></p>

<h3>Module</h3>

<p>今まで、モジュールをインポート・エクスポートする様々なライブラリが作られてきましたが、この機能が公式のものとして提供されることになりました。</p>

<p></p><pre class="crayon-plain-tag">module 'math' {
  export function sum(x, y) {
    return x + y;
  }
  export var hbar = 1.054571726e-34; // ディラック定数
}</pre><p></p>

<p></p><pre class="crayon-plain-tag">import {sum, hbar} from 'math';
alert("2ħ = " + sum(hbar, hbar));

// オブジェクトのプロパティに読み込み
module Math from 'math';
alert("2ħ = " + Math.sum(Math.hbar, Math.hbar));</pre><p></p>

<h2>Readable Code</h2>

<h3>Arrow Function</h3>

<p>今まで、コールバックとして関数を渡す際に「function(&#8230;){&#8230;}」と記述する必要があり、ソースコードが冗長で見にくくなっていましたが、Arrow Functionを使うことでこの関数をシンプルに記載できるようになります。</p>

<p></p><pre class="crayon-plain-tag">// return するだけのコールバックがシンプルに
[1,2,3].map(x =&gt; x * x);
// ES5 ではこう書く必要があった:
// [1,2,3].map(function (x) { return x * x; });

// n! (nの階乗) を求める関数もシンプルに
var factorial=((f=n=&gt;n&gt;1 ?n*f(n-1):1)=&gt;(f))();
factorial(10); // 3628800</pre><p></p>

<p>Arrow Functionには、簡潔に書けるということに加えて、もう一つ良いことがあります。それは、thisが保持・バインドされるということです。今まで、コールバック関数内で呼び出し元のオブジェクトを参照しようとすると、thisがwindowオブジェクトを参照するようになるため、コールバック関数の前で「self = this」などと記載し、この場合はコールバック関数内で「self」を参照しなければなりませんでした。Arrow Functionですと、Arrow Function内のthisが、その外側の関数のthisを参照し続けるという特性があり、このような記載が不要となります。</p>

<h3>Generator</h3>

<p>nextメソッドを持ち、繰り返し処理が実行される際にnextメソッドが呼ばれる特殊なオブジェクトをイテレータ(iterator)と呼びます。イテレータを簡単に生成できるジェネレータ関数によって生成されたイテレータをジェネレータ(generator)と呼びます。ジェネレータ関数では、yieldというキーワードがreturnの代わりに使われており、yieldが実行されるとその引数が返却されて関数の処理が一時停止します。そして、再度関数が実行されるとyieldの次の行から処理が再開し、またyieldが実行されると引数を返却して処理が一時停止する、という処理の流れになります。ジェネレータ関数を使うことで、関数の再起呼び出しを行うことなく、何かしらの繰り返しの処理を行うことができます。</p>

<p></p><pre class="crayon-plain-tag">// ジェネレータ関数 (ジェネレータのコンストラクタ)
function* fibonacci() {
  let [prev, curr] = [0, 1];
  for (;;) {
    [prev, curr] = [curr, prev + curr];
    yield curr; // 値を返して一時停止
  }
}
for (n of fibonacci()) {
  if (n &gt; 20)
    break;
  console.log(n); // 順に 1, 2, 3, 5, 8, 13
}</pre><p></p>

<p>先ほどのfor&#8230;ofの中でジェネレータ関数を使う方法以外にも、毎回明示的にイテレートする方法があります。こちらがイテレータの本来の使い方なのですが、例えば、カウンタを作成する場合、毎回一時停止して内部で保持している値をインクリメントするジェネレータ関数を定義すると、nextメソッドを呼ぶたびにインクリメントされた値を取得する処理を実装することができます。</p>

<p></p><pre class="crayon-plain-tag">function* counterGenerator() {
  let c = 0;
  for (;;) {
    yield c++; // 値を返して一時停止
  }
}
// ジェネレータを生成
let counter = counterGenerator();
// next() メソッドで {value, done} を得る
counter.next(); // -&gt; {value: 0, done: false}
counter.next(); // -&gt; {value: 1, done: false}
counter.next().value; // -&gt; 2
counter.next().value; // -&gt; 3</pre><p></p>

<h3>Promise</h3>

<p>Promiseを使うことで、今までよりもコールバックを非常に簡潔に書けるようになります。また、catchなどの構文も今まで以上に書きやすくなります。Promiseを生成するときに引数として関数を渡し、そこでresolve関数とreject関数を指定します。このresolve関数が呼ばれたときにこのPromiseインスタンスが解決し、このインスタンスのthenメソッドが実行されます。</p>

<p></p><pre class="crayon-plain-tag">let p = new Promise(function (resolve, reject) {
  // 3 秒後に resolve 呼んでプロミスが解決する
  setTimeout(resolve, 3000);
});

// 解決した (resolve が呼ばれた) ときに実行:
p.then(function () {
  alert('3 秒たったよ!');
}).then(function () {
  // 解決済みなので即ここも実行される
  alert('既に 3 秒過ぎてるよ!');
});</pre><p></p>

<p></p><pre class="crayon-plain-tag">p = new Promise(function (resolve, reject) {
  dream(); // 未定義の関数を呼ぶ (エラー発生)
});

// エラー発生時は then をスキップして catch へ
p.then(function (message) {
  // p は解決しないのでこのブロックは実行されない
  alert(message);
}).catch(function (error) {
  // p でエラーが発生するのでこのブロックを実行
  alert(error);
  // -&gt; ReferenceError: dream is not defined
});</pre><p></p>

<h2>New Type &amp; API</h2>

<h3>Collections</h3>

<p>Set型、Map型が追加されます。Setを使うことで、集合に対して要素を追加したり参照したりすることができます。Mapは、キーとそれに対応する値を保持できるものです。配列やオブジェクトではキーとして文字列しか設定できませんでしたが、Mapではキーとしてオブジェクトを設定することができます。</p>

<p></p><pre class="crayon-plain-tag">var set = new Set();
// 集合に追加・確認・削除
set.add("Firefox");
set.add("Thunderbird");
set.add(+0);
set.add(NaN);
set.has("Firefox"); // -&gt; true
set.has("Sunbird"); // -&gt; false
set.delete("Firefox");
set.has("Firefox"); // -&gt; false
// -0 と +0 は区別される, NaN は区別されない
set.has(-0); // -&gt; false
set.has(NaN); // -&gt; true</pre><p></p>

<p></p><pre class="crayon-plain-tag">var map = new Map();
var str = "Mozilla", obj = {}, func = function(){};
// Map に値を格納
map.set(str, "Firefox");
map.set(obj, "Thunderbird");
map.set(func, "Japan");
// キーに対応する値を取得
map.get(str); // -&gt; "Firefox"
map.get(obj); // -&gt; "Thunderbird"
map.get(func); // -&gt; "Japan"
// 設定したキーと引数の比較は == ではないので注意
map.get("Mozilla"); // -&gt; "Firefox"
map.get({}); // -&gt; undefined
map.get(function(){}) // -&gt; undefined</pre><p></p>

<p>ここまで次世代言語仕様の一部をご紹介してきましたが、このようにJavaScriptは構文や機能面でも大きな進化を遂げ、落とし穴が少なくシンプルな記法で書ける言語に進化するのです。<br>
そして一方、広く使われる言語は書きやすいだけでなく高速でなければなりませんが、ここからは速度面の進化についてご紹介します。</p>

<h2>Slow Parts &amp; Fast Parts</h2>

<p>JavaScriptが遅い原因として、JavaScriptが動的型付け言語であることや、JavaScriptにクラスと配列が存在しないことなどがありますが、これらの原因を回避して、JavaScriptエンジンが最適化しやすいコードだけを書くようにすることで、処理を高速化させることができます。例えば、型固定で変数を定義することや、一度定義したオブジェクトのプロパティの追加・削除を行わない、といったことなどに気をつければ、処理を高速化させることができます。このように、JavaScriptエンジンが最適化しやすく、高速化を図れるコードを、私の中で「JavaScript Fast Parts」と呼んでいます。</p>

<h3>Typed Array</h3>

<p>Fast Partsの代表的なものとして、Typed Arrayがあります。これを使うことで、今までJavaScriptではできなかった静的型付け・型の固定を行うことができます。</p>

<p></p><pre class="crayon-plain-tag">// 16 バイト長のバッファを確保
var buffer = new ArrayBuffer(16);
// 32bit 整数 x 4 として読み出すビューを定義
var int32View = new Int32Array(buffer);
// 32bit 整数として 0, 2, 4, 6 を格納
for (var i=0; i&lt;int32View.length; i+ +) { int32View[i]=i*2; }
// 16bit 整数 x 8 として同じバッファを読み出すビュー
var int16View = new Int16Array(buffer); // 実際に読み出してみる
for (var i=0; i&lt;int16View.length; i++) {
	console.log(int16View[i]);
}
// -&gt; 0, 0, 2, 0, 4, 0, 6, 0</pre><p></p>

<h2>asm.js</h2>

<p>以上のような高速化できる方法だけを使ってコードを書く、ということをあらかじめルールとして定めてしまい、JavaScriptエンジン側も最初から最適化された状態でコンパイルして高速に実行するようにしよう、という発想に基づいた高速化方法を、Mozillaがasm.jsとして提案しています。コードを自動生成するための様々なツールが存在していますが、これらは全て、JavaScriptエンジンが速く実行できるコードを生成しようとしています。このように、既存のエンジンにおける高速化のノウハウがある程度溜まっているため、それらのノウハウを結晶させたFast Partsを使って高速化を実現させるということが、asm.jsの発想です。</p>

<p>asm.jsの目的は、WebをNativeと同様の速度にすることです。Native同様の速度にするために、新しいコンパイルの方法を導入したりするわけではありません。現在のJavaScriptエンジンでも、最適化できるコードに関しては、既に型固定の高速なコードが生成されるようになっています。その際に、コード生成のためのオーバーヘッドや型変換時のチェックなどがあり、これらがなければNative並みの速度で実行されるようになりつつあります。このエンジンをそのまま利用して、今まで「このコードを最適化して良いか否か」をヒューリスティックに判別していたところを、asm.jsを利用すると、決め打ちで最適化できるようなります。</p>

<p>既存のJavaScriptエンジンでも、よく使われるコードを見つけて、それらを最適化することが幅広く行われています。しかし、簡単なコードは最適化できても、巨大なコードは最適化できない場合が多く、C言語よりも10倍、20倍遅い場合もあります。asm.jsを利用し、常に最適化するようにした場合は、asm.js導入直後の時点でもC言語の2倍の速度で済むレベルまで高速化されました。asm.jsでの高速化は、現在も改良が進められています。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2013/12/html5conference-report-javascript-02.jpg" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/html5conference-report-javascript-02.jpg" alt="html5conference-report-javascript-02" width="520" height="390" class="aligncenter size-full wp-image-3615" style="border: 1px solid #000000" /></a></p>

<h2>結論：Always bet on JavaScript!</h2>

<p>Webは非常に互換性を重視しており、既存のものを動作させ続けながら、機能を追加したり速度を改善したりする必要があります。本日ご説明しました通り、JavaScriptでは、必要な機能の追加や高速化が順次行われているため、JavaScriptはこれまで同様に生き続け、皆さんが勉強する価値のある言語になっていると思っており、これからもJavaScriptを愛して頂ければ嬉しいです。</p>


<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe src="http://www.slideshare.net/slideshow/embed_code/28756192" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" 0="allowfullscreen" class="iframe-class"></iframe>


<div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/dynamis/ecmascript-2013" title="JavaScript (ECMAScript) 2013" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">JavaScript (ECMAScript) 2013</a> </strong> from <strong><a href="http://www.slideshare.net/dynamis" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">dynamis .</a></strong> </div>

<p><br>

<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe width="560" height="315" src="//www.youtube.com/embed/22MgGmhcmPs" frameborder="0" 0="allowfullscreen" scrolling="yes" class="iframe-class"></iframe>
</p>
]]></content:encoded>
		
		<series:name><![CDATA[HTML5 Conference 2013レポート]]></series:name>
	</item>
	</channel>
</rss>
