<?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 2015（ECMAScript 6）特集 &#8211; HTML5Experts.jp</title>
	<atom:link href="/series/ecma2015/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>テンプレートエンジン不要？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>
	</channel>
</rss>
