diff options
author | Masahiro FUJIMOTO <mfujimot@gmail.com> | 2021-05-06 02:13:30 +0900 |
---|---|---|
committer | potappo <potappo@gmail.com> | 2021-05-09 23:24:27 +0900 |
commit | 7b90ddeb227a0977113bbb6ab0393d95159b500c (patch) | |
tree | 79f55170af7acbe4cff088f3f063bf2401706b9f /files/ja/web/javascript/a_re-introduction_to_javascript/index.html | |
parent | 64dfe2f6228e59797bb3ec2a273e3c65b7910c70 (diff) | |
download | translated-content-7b90ddeb227a0977113bbb6ab0393d95159b500c.tar.gz translated-content-7b90ddeb227a0977113bbb6ab0393d95159b500c.tar.bz2 translated-content-7b90ddeb227a0977113bbb6ab0393d95159b500c.zip |
Web/JavaScript/A_re-introduction_to_JavaScript を更新
- 2021/04/28 時点の英語版に同期
- 原語併記マクロを削除
Diffstat (limited to 'files/ja/web/javascript/a_re-introduction_to_javascript/index.html')
-rw-r--r-- | files/ja/web/javascript/a_re-introduction_to_javascript/index.html | 608 |
1 files changed, 321 insertions, 287 deletions
diff --git a/files/ja/web/javascript/a_re-introduction_to_javascript/index.html b/files/ja/web/javascript/a_re-introduction_to_javascript/index.html index 78801c66eb..490134dc97 100644 --- a/files/ja/web/javascript/a_re-introduction_to_javascript/index.html +++ b/files/ja/web/javascript/a_re-introduction_to_javascript/index.html @@ -13,205 +13,228 @@ translation_of: Web/JavaScript/A_re-introduction_to_JavaScript --- <div>{{jsSidebar}}</div> -<p>なぜ {{原語併記("「再」入門", "re-introduction")}} なのか? なぜなら {{Glossary("JavaScript")}} は<a href="http://javascript.crockford.com/javascript.html">世界で最も誤解されたプログラミング言語</a>としてよく知られているためです。しばしばおもちゃだと馬鹿にされながら、しかしその人を欺くような単純さの下に、強力な言語機能が隠されているのです。JavaScript は数々の高い注目を集めるアプリケーションで使用され、この技術の深い知識がどんなウェブやモバイルの開発者にとっても重要なスキルであることが示されました。</p> +<p>なぜ「再」入門なのでしょうか。それは、 <a href="/ja/docs/Glossary/JavaScript">JavaScript</a> が誤解されていることで有名だからです。しばしばおもちゃだと馬鹿にされながら、しかしその嘘のような単純さの下に、強力な言語機能が隠されているのです。 JavaScript はとても多くの著名なアプリケーションで使用されるようになっており、この技術の深い知識が、あらゆるウェブやモバイルの開発者にとって重要なスキルであることを示しています。</p> -<p>この言語の歴史について理解することから始めるのが役立つでしょう。JavaScript は 1995 年、Netscape の技術者{{原語併記("ブレンダン・アイク", "Brendan Eich")}} によって創られ、1996 年初頭に Netscape 2 で初めてリリースされました。当初は LiveScript と呼ばれる予定でしたが、Sun Microsystems の Java 言語の人気にあやかろうという不運なるマーケティング上の決定により改名されました ― 2 つの言語が共通点をほとんど持っていないにもかかわらず。それ以来、このことは未だに混同の元となっています。</p> +<p>まずは、この言語の歴史を振り返ってみましょう。 JavaScript は、 1995 年に Netscape 社のエンジニアだった Brendan Eich 氏によって開発されました。 JavaScript は、 1996 年の初めに Netscape 2 とともにリリースされました。当初は LiveScript と呼ばれる予定でしたが、 Sun Microsystems の Java 言語の人気にあやかろうとしたマーケティング上の不運な決定により、両者にはほとんど共通点がないにもかかわらず改名されました。このことは、いまだに混同の元となっています。</p> -<p>Microsoft はその数か月後、IE3 とともに JScript というほとんど互換性のある言語をリリースしました。さらに数か月後、Netscape はこの言語をヨーロッパの標準化団体 <a href="http://www.ecma-international.org/">Ecma International</a> に提出し、その結果 1997 年に {{Glossary("ECMAScript")}} という標準の第 1 版が生まれました。この標準は重要なアップデートを受けて 1999 年に <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript 第 3 版</a>となり、その後しばらくほとんど安定してきました。言語の複雑化に関する政治的な隔たりから、第 4 版は放棄されたものの、その多くのパーツは 2009 年 12 月に発行された新しい ECMAScript 第 5 版の基礎となりました。そして、標準の第 6 版が 2015 年 6 月に発行されました。</p> +<p>その数か月後、 Microsoft は Internet Explorer 3 とともに JScript をリリースしました。これはほぼ互換性のある JavaScript の互換品でした。さらに数か月後、 Netscape はこの言語をヨーロッパの標準化団体である <a href="https://www.ecma-international.org/">Ecma International</a> に提出し、その結果、同年に <a href="/ja/docs/Glossary/ECMAScript">ECMAScript</a> という標準の第 1 版が生まれました。この標準は 1999 年に <a href="https://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript 第 3 版</a>として大幅に更新され、それ以降はほぼ安定しています。第 4 版は、言語の複雑化に関する政治的な見解の相違から放棄されました。第 4 版の多くの部分は、 2009 年 12 月に発行された新しい ECMAScript 第 5 版と、 2015 年 6 月に発行された第 6 版の基礎になりました。</p> -<div class="note">なじみ深いため、ここからは ECMAScript を "JavaScript" と呼びます。</div> +<div class="note"> +<p><strong>注:</strong> より馴染んでいるため、ここからは ECMAScript を "JavaScript" と呼ぶことにします。</p> +</div> -<p>大部分のプログラミング言語と違って、JavaScript という言語には入出力の概念がありません。この言語はあるホスト環境でのスクリプト言語として実行されるよう設計されており、外部の世界とコミュニケーションするための機構はそのホスト環境が提供するものとしているのです。もっとも一般的なホスト環境はブラウザーですが、JavaScript のインタープリターは Adobe Acrobat や Photoshop、SVG 画像、Yahoo! ウィジェットエンジン、さらには <a href="http://nodejs.org/" title="nodejs.org">Node.js</a> といったサーバーサイド環境、オープンソースの <a href="http://couchdb.apache.org/">Apache CouchDB</a> といった NoSQL データベース、組み込みコンピューター、<a href="http://www.gnome.org/">GNOME</a> (GNU/Linux オペレーティングシステムでもっとも人気がある GUI 環境のひとつ) のようなデスクトップ環境など、さまざまなところでみられます。</p> +<p>大部分のプログラミング言語と違って、 JavaScript という言語には入出力の概念がありません。この言語はあるホスト環境でのスクリプト言語として実行されるよう設計されており、外部の世界とコミュニケーションするための機構はそのホスト環境が提供するものとしているのです。もっとも一般的なホスト環境はブラウザーですが、JavaScript のインタープリターは Adobe Acrobat や Photoshop、SVG 画像、Yahoo! ウィジェットエンジン、さらには <a href="https://nodejs.org/">Node.js</a> といったサーバーサイド環境、オープンソースの <a href="https://couchdb.apache.org/">Apache CouchDB</a> のような NoSQL データベース、組み込みコンピューター、<a href="https://www.gnome.org/">GNOME</a> (GNU/Linux オペレーティングシステムでもっとも人気がある GUI 環境のひとつ) のようなデスクトップ環境など、さまざまなところでみられます。</p> -<h2 id="Overview" name="Overview">概要</h2> +<h2 id="Overview">概要</h2> -<p>JavaScript はマルチパラダイムの動的言語であり、型や演算子、標準組み込みオブジェクト、メソッドがあります。その構文は Java や C 言語に由来するので、それらの言語の多くの構造が JavaScript にも同様に適用できます。JavaScript は、クラスではなくオブジェクトプロトタイプによるオブジェクト指向プログラミングをサポートします (詳しくは <a href="/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain" title="prototypical inheritance">プロトタイプの継承</a> や ES2015 の <a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes">classes</a> をご覧ください)。また、JavaScript は関数型プログラミングもサポートします。関数もオブジェクトであり、関数に実行可能なコードを持たせて、他のオブジェクトと同じように受け渡しさせることができます。</p> +<p>JavaScript はマルチパラダイムの動的言語であり、型や演算子、標準組み込みオブジェクト、メソッドがあります。その構文は Java や C 言語に由来するので、それらの言語の多くの構造が JavaScript にも同様に適用できます。JavaScript は、クラスの代わりにオブジェクトプロトタイプによるオブジェクト指向プログラミングをサポートします (詳しくは <a href="/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain" title="prototypical inheritance">プロトタイプの継承</a> や ES2015 の <a href="/ja/docs/Web/JavaScript/Reference/Classes">classes</a> をご覧ください)。また、JavaScript は関数型プログラミングもサポートします。関数もオブジェクトであり、関数に実行可能なコードを持たせて、他のオブジェクトと同じように受け渡しすることができます。</p> -<p>まずはあらゆる言語の構成要素、「型」を見ることから始めましょう。JavaScript のプログラムは値を操作し、それらの値はすべて型に属しています。JavaScript の型は:</p> +<p>まずはあらゆる言語の構成要素、「型」を見ることから始めましょう。 JavaScript のプログラムは値を操作し、それらの値はすべて型に属しています。JavaScript の型は次の通りです。</p> <ul> - <li>{{jsxref("Number", "数値")}}</li> - <li>{{jsxref("String", "文字列")}}</li> - <li>{{jsxref("Boolean", "真偽値")}}</li> - <li>{{jsxref("Function", "関数")}}</li> - <li>{{jsxref("Object", "オブジェクト")}}</li> - <li>{{jsxref("Symbol")}} (ES2015 の新オブジェクト)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#number_type">Number</a> (数値型)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#bigint_type">BigInt</a> (長整数型)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#string_type">String</a> (文字列型)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#boolean_type">Boolean</a> (論理型)</li> + <li>{{jsxref("Function")}} (関数)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#objects">Object</a> (オブジェクト型)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#symbol_type">Symbol</a> (シンボル型、ES2015 で新登場)</li> </ul> -<p>...ああ、あと {{jsxref("undefined")}} と {{jsxref("null")}}、これらはちょっと変わっています。そして {{jsxref("Array", "Array (配列)")}}、これは特殊なオブジェクトの一種。さらに {{jsxref("Date")}} と {{jsxref("RegExp", "RegExp (正規表現)")}}、これらは自由に使えるオブジェクトです。あと技術的に正確なことを言うと、関数は単にオブジェクトの特殊な型です。したがってこの型の図はより正確にはこうなります:</p> +<p>...ああ、あと <a href="/ja/docs/Web/JavaScript/Data_structures#undefined_type">undefined</a> と <a href="/ja/docs/Web/JavaScript/Data_structures#null_type">null</a>、これらはちょっと変わっています。そして {{jsxref("Array")}} (配列)、これは特殊なオブジェクトの一種。さらに {{jsxref("Date")}} (日付) と {{jsxref("RegExp")}} (正規表現)、これらは自由に使えるオブジェクトです。あと技術的に正確なことを言うと、関数もオブジェクトの特殊な型です。したがって、この型の図はより正確にはこうなります。</p> <ul> - <li>{{jsxref("Number", "数値")}}</li> - <li>{{jsxref("String", "文字列")}}</li> - <li>{{jsxref("Boolean", "真偽値")}}</li> - <li>{{jsxref("Symbol")}} (ES2015 の新オブジェクト)</li> - <li>{{jsxref("Object", "オブジェクト")}} + <li><a href="/ja/docs/Web/JavaScript/Data_structures#number_type">Number</a> (数値型)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#bigint_type">BigInt</a> (長整数型)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#string_type">String</a> (文字列型)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#boolean_type">Boolean</a> (論理型)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#symbol_type">Symbol</a> (シンボル型、ES2015 で新登場)</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#objects">Object</a> (オブジェクト型) <ul> - <li>{{jsxref("Function", "関数")}}</li> - <li>{{jsxref("Array", "Array (配列)")}}</li> - <li>{{jsxref("Date")}}</li> - <li>{{jsxref("RegExp", "RegExp (正規表現)")}}</li> + <li>{{jsxref("Function")}} (関数)</li> + <li>{{jsxref("Array")}} (配列)</li> + <li>{{jsxref("Date")}} (日付)</li> + <li>{{jsxref("RegExp")}} (正規表現)</li> </ul> </li> - <li>{{jsxref("null")}}</li> - <li>{{jsxref("undefined")}}</li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#null_type">null</a></li> + <li><a href="/ja/docs/Web/JavaScript/Data_structures#undefined_type">undefined</a></li> </ul> <p>さらにいくつかの組み込み {{jsxref("Error")}} 型もあります。しかし、最初の図のままでいく方が物事はとても簡単になるでしょうから、当面は最初の図で説明します。</p> -<h2 id="Numbers" name="Numbers">数値</h2> +<h2 id="Numbers">数値</h2> + +<p>ECMAScript には 2 つの組み込み数値型があります。 <strong>Number</strong> と <strong>BigInt</strong> です。</p> -<p>JavaScript における数値は、仕様によると「{{原語併記("倍精度 64 ビットフォーマット IEEE 754 値", "double-precision 64-bit format IEEE 754 values")}}」です。 JavaScript には整数に当たるものがない ( {{jsxref("BigInt")}} を除く) ので、少し気を付ける必要があります。以下の例を見てください。</p> +<p>Number 型は<a href="https://ja.wikipedia.org/wiki/%E5%80%8D%E7%B2%BE%E5%BA%A6%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0">IEEE 754 倍精度 64 ビットバイナリー値</a> (-(2<sup>53</sup> − 1) と 2<sup>53</sup> − 1 の間の数) です。そして、この記事や他の MDN の記事で「整数」という場合は、ふつう Number 値を使った整数の<em>表現</em>を意味しています。しかし、このような Number 値は本物の整数ではないので、少し注意が必要です。以下の例を見てください。</p> -<pre class="brush: js notranslate">console.log(3 / 2); // 1.5, <em>not</em> 1 +<pre class="brush: js">console.log(3 / 2); // 1.5, 1 <em>ではない</em> console.log(Math.floor(3 / 2)); // 1</pre> -<p>したがって、見かけ上の整数は実際には暗黙的に浮動小数点数となります。</p> +<p>したがって、<em>見かけ上は整数</em>でも、実際には<em>暗黙的に浮動小数点数</em>となります。</p> -<p>また、以下のようなことに注意してください:</p> +<p>また、次のようなことに注意してください。</p> -<pre class="brush: js notranslate">0.1 + 0.2 == 0.30000000000000004; +<pre class="brush: js">0.1 + 0.2 == 0.30000000000000004; </pre> -<p>実のところ、整数値は 32 ビット int 型として扱われます。また一部の実装では、32 ビット整数値ではなく Number で有効な命令の実行を求められるまでの間、32 ビット整数値として保存します。これはビット演算を行う際に重要なことです。</p> +<p>実のところ、整数値は 32 ビット整数として扱われます。また一部の実装では、32 ビット整数値ではなく Number で有効な命令の実行を求められるまでの間、32 ビット整数値として保存します。これはビット演算を行う際に重要なことです。</p> -<p>足し算、引き算、モジュロ (剰余) など、標準的な <a href="/ja/docs/Web/JavaScript/Reference/Operators#Arithmetic_operators">算術演算</a> がサポートされています。さらに、これは先ほど言及し忘れたのですが、より高度な数学関数や定数を扱う {{jsxref("Math")}} という組み込みオブジェクトもあります:</p> +<p>標準的な<a href="/ja/docs/Web/JavaScript/Reference/Operators#arithmetic_operators">算術演算子</a>に対応しています。例えば、足し算、引き算、モジュロ (剰余) などです。さらに、これは前に言及していなかったのですが、より高度な数学関数や定数を扱う {{jsxref("Math")}} という組み込みオブジェクトもあります。</p> -<pre class="brush: js notranslate">Math.sin(3.5); +<pre class="brush: js">Math.sin(3.5); var circumference = 2 * Math.PI * r; </pre> -<p>あなたは組み込みの {{jsxref("Global_Objects/parseInt", "parseInt()")}} 関数を使うことで、文字列を整数に変換することができます。この関数は省略可能な第 2 引数として変換の基数を取りますが、あなたは常にこの引数を与えるべきです:</p> +<p>組み込みの {{jsxref("Global_Objects/parseInt", "parseInt()")}} 関数を使うことで、文字列を整数に変換することができます。この関数は省略可能な第 2 引数として変換の基数を取りますが、この引数を常に指定してください。</p> -<pre class="brush: js notranslate">parseInt('123', 10); // 123 +<pre class="brush: js">parseInt('123', 10); // 123 parseInt('010', 10); // 10 </pre> -<p>古いブラウザーでは "0" から始まる文字列を 8 進数 (基数 8) とみなしますが、これは 2013 年以降のブラウザーにはあてはまりません。文字列の形式を理解していなければ、古いブラウザーであなたは驚くような結果を得ることでしょう:</p> +<p>古いブラウザーでは、 "0" から始まる文字列を 8 進数 (基数 8) とみなしますが、これは 2013 年以降のブラウザーにはあてはまりません。文字列の書式を理解していなければ、古いブラウザーは驚くような結果になることがあります。</p> -<pre class="brush: js notranslate">parseInt('010'); // 8 +<pre class="brush: js">parseInt('010'); // 8 parseInt('0x10'); // 16 </pre> -<p>この例では、{{jsxref("Global_Objects/parseInt", "parseInt()")}} が最初の文字列を先頭の 0 から 8 進数として、また 2 番目の文字列を先頭の "0x" から 16 進数として扱ったことがわかります。<em>16 進数表記は現在も有効です</em>。8 進数のみ削除されました。</p> +<p>この例では、{{jsxref("Global_Objects/parseInt", "parseInt()")}} が最初の文字列を先頭の 0 から 8 進数として、また 2 番目の文字列を先頭の "0x" から 16 進数として扱われたことがわかります。<em>16 進数表記は現在も有効です</em>。8 進数のみ削除されました。</p> -<p>もし 2 進数を整数に変換したいなら、単純に基数を変えましょう:</p> +<p>もし 2 進数を整数に変換したいなら、単純に基数を変えましょう。</p> -<pre class="brush: js notranslate">parseInt('11', 2); // 3 +<pre class="brush: js">parseInt('11', 2); // 3 </pre> -<p>同様に浮動小数点数への変換を行う、組み込みの {{jsxref("Global_Objects/parseFloat", "parseFloat()")}} 関数があります。こちらは {{jsxref("Global_Objects/parseInt", "parseInt()")}} と異なり、基数は常に 10 が用いられます。</p> +<p>同様に浮動小数点数への変換を行う、組み込みの {{jsxref("Global_Objects/parseFloat", "parseFloat()")}} 関数があります。 {{jsxref("Global_Objects/parseInt", "parseInt()")}} と異なり、 <code>parseFloat()</code> では基数は常に 10 が用いられます。</p> -<p>また、単項演算子 <code>+</code> を使って値を数値に変換することもできます:</p> +<p>また、単項演算子 <code>+</code> を使って値を数値に変換することもできます。</p> -<pre class="brush: js notranslate">+ '42'; // 42 +<pre class="brush: js">+ '42'; // 42 + '010'; // 10 + '0x10'; // 16 </pre> -<p>もし文字列が数でない場合、 {{jsxref("NaN")}} (非数、"Not a Number" の略) と呼ばれる特別な値が返ります:</p> +<p>もし文字列が数値でない場合、 {{jsxref("NaN")}} (非数、"Not a Number" の略) と呼ばれる特別な値が返されます。</p> -<pre class="brush: js notranslate">parseInt('hello', 10); // NaN +<pre class="brush: js">parseInt('hello', 10); // NaN </pre> -<p><code>NaN</code> には毒性があります: これを入力してどの算術演算に与えても、その結果は同様に <code>NaN</code> になるのです:</p> +<p><code>NaN</code> には毒性があります。これを算術演算に入力として与えても、その結果は同様に <code>NaN</code> になるのです。</p> -<pre class="brush: js notranslate">NaN + 5; // NaN +<pre class="brush: js">NaN + 5; // NaN </pre> -<p>組み込みの {{jsxref("Global_Objects/isNaN", "isNaN()")}} 関数を使えば、<code>NaN</code> であるかを検査することができます:</p> +<p><code>NaN</code> であるかどうかを確実に確認するには、組み込みの {{jsxref("Number.isNaN", "Number.isNaN()")}} 関数を使用してください。この関数は、<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#description">名前が示す通りの動作</a>をします。</p> -<pre class="brush: js notranslate">isNaN(NaN); // true +<pre class="brush: js">Number.isNaN(NaN); // true +Number.isNaN('hello'); // false +Number.isNaN('1'); // false +Number.isNaN(undefined); // false +Number.isNaN({}); // false +Number.isNaN([1]) // false +Number.isNaN([1,2]) // false </pre> -<p>JavaScript はまた、特別な値 {{jsxref("Infinity")}} と <code>-Infinity</code> を持っています:</p> +<p>しかし、 <code>NaN</code> であるかどうかをグローバル関数の {{jsxref("Global_Objects/isNaN", "isNaN()")}} で確認しないでください。<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/isNaN#confusing_special-case_behavior">これは直感的でない動作</a>をします。</p> + +<pre class="brush: js">isNaN('hello'); // true +isNaN('1'); // false +isNaN(undefined); // true +isNaN({}); // true +isNaN([1]) // false +isNaN([1,2]) // true +</pre> -<pre class="brush: js notranslate"> 1 / 0; // Infinity +<p>JavaScript はまた、特別な値 {{jsxref("Infinity")}} と <code>-Infinity</code> を持っています。</p> + +<pre class="brush: js"> 1 / 0; // Infinity -1 / 0; // -Infinity </pre> -<p>組み込みの {{jsxref("Global_Objects/isFinite", "isFinite()")}} 関数を使えば、<code>Infinity</code>、<code>-Infinity</code>、<code>NaN</code> であるかを検査することができます:</p> +<p><code>Infinity</code>、<code>-Infinity</code>、<code>NaN</code> であるかをどうかは、組み込みの {{jsxref("Global_Objects/isFinite", "isFinite()")}} 関数を使用して確認することができます。</p> -<pre class="brush: js notranslate">isFinite(1 / 0); // false +<pre class="brush: js">isFinite(1 / 0); // false isFinite(-Infinity); // false isFinite(NaN); // false </pre> -<div class="note">{{jsxref("Global_Objects/parseInt", "parseInt()")}} および {{jsxref("Global_Objects/parseFloat", "parseFloat()")}} 関数は文字列を、規定の数値書式に該当しない文字が現れるまで解析し、その箇所までの数値を返します。一方、"+" 演算子は適切でない文字を含む文字列を <code>NaN</code> に変換します。ご自身でコンソールを用いて、文字列 "10.2abc" をそれぞれの方法で解析させるとその違いがよくわかるでしょう。</div> +<div class="note"><p><strong>注:</strong> {{jsxref("Global_Objects/parseInt", "parseInt()")}} および {{jsxref("Global_Objects/parseFloat", "parseFloat()")}} 関数は文字列を、規定の数値書式に該当しない文字が現れるまで解釈し、その箇所までの数値を返します。一方、"+" 演算子は適切でない文字を含む文字列を <code>NaN</code> に変換します。コンソールから、文字列 "10.2abc" をそれぞれの方法で解釈させるとその違いがよくわかるでしょう。</p></div> -<h2 id="Strings" name="Strings">文字列</h2> +<h2 id="Strings">文字列</h2> -<p>JavaScript における文字列は、<a href="/ja/docs/Web/JavaScript/Guide/Values,_variables,_and_literals#Unicode">Unicode 文字</a> の{{原語併記("連なったもの", "sequences")}} です。これは{{原語併記("国際化", "internationalization")}} に対処しなければならない誰もが歓迎するニュースでしょう。より正確に言えば UTF-16 コード単位の連なったものであり、つまりそれぞれのコード単位は 16 ビットの整数で表されます。また、それぞれの Unicode 文字は 1 または 2 個のコード単位で表します。</p> +<p>JavaScript における文字列は、<a href="/ja/docs/Web/JavaScript/Guide/Grammar_and_types#unicode">Unicode 文字</a>の並びです。これは、国際化を扱う必要があった誰もが歓迎する知らせでしょう。より正確に言えば UTF-16 コード単位の連なったものであり、つまりそれぞれのコード単位は 16 ビットの整数で表されます。また、それぞれの Unicode 文字は 1 または 2 個のコード単位で表します。</p> -<p>もし単一文字を表したいなら、単純に 1 文字で構成された文字列を使います。</p> +<p>もし単一の文字を表したいなら、単純に 1 文字で構成された文字列を使います。</p> -<p>文字列の長さ (コード単位) を知るには、その文字列の <code><a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/String/length">length</a></code> プロパティにアクセスしましょう:</p> +<p>文字列の長さ (コード単位) を知るには、その文字列の <code><a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/String/length">length</a></code> プロパティにアクセスしましょう。</p> -<pre class="brush: js notranslate">'hello'.length; // 5 +<pre class="brush: js">'hello'.length; // 5 </pre> -<p>JavaScript のオブジェクトとの初めての接触です! 私、文字列も {{jsxref("Object", "オブジェクト", "", 1)}} であると言いましたっけ? 文字列はまた、文字列の操作や文字列に関する情報へのアクセスを可能にする {{jsxref("String", "メソッド", "#Methods", 1)}} も持っています:</p> +<p>ここで初めて JavaScript のオブジェクトに触れました。文字列を{{jsxref("Object", "オブジェクト", "", 1)}}のように使うことができることには、既に触れましたっけ?文字列にも{{jsxref("String", "メソッド", "#instance_methods", 1)}}があり、文字列を操作したり、文字列に関する情報にアクセスしたりすることができます。</p> -<pre class="brush: js notranslate">'hello'.charAt(0); // "h" -'hello, world'.replace('hello', 'goodbye'); // "goodbye, world" +<pre class="brush: js">'hello'.charAt(0); // "h" +'hello, world'.replace('world', 'mars'); // "hello, mars" 'hello'.toUpperCase(); // "HELLO" </pre> -<h2 id="Other_types" name="Other_types">その他の型</h2> +<h2 id="Other_types">その他の型</h2> -<p>JavaScript は {{jsxref("null")}} と {{jsxref("undefined")}} を区別します。<code>null</code> は、意図的に「値がない」ということを指し示す値です (また、<code>null</code> キーワードによってのみアクセスできます)。対して <code>undefined</code> とは、初期化されていない値 ― すなわち、「まだ値が代入されていない」ということを指し示す undefined 型の値です。変数については後で話しますが、JavaScript では値を代入しないで変数を宣言することができるのです。そのようにした場合、その変数の型は <code>undefined</code> です。実際は、<code>undefined</code> は定数です。</p> +<p>JavaScript は {{jsxref("null")}} と {{jsxref("undefined")}} を区別します。 <code>null</code> は、意図的に値がないことを示す値です (また、<code>null</code> キーワードによってのみアクセスできます)。対して <code>undefined</code> とは、初期化されていない値 — すなわち、まだ値が代入されていないことを示す <code>undefined</code> 型の値です。変数については後で話しますが、 JavaScript では値を代入しないで変数を宣言することができるのです。そのようにした場合、その変数の型は <code>undefined</code> です。実際は、<code>undefined</code> は定数です。</p> -<p>JavaScript は <code>true</code> と <code>false</code> (これらはともにキーワードです) を取りうる値とする真偽値型を持っています。どんな値でも以下のルールに基づいて真偽値に変換できます:</p> +<p>JavaScript は <code>true</code> と <code>false</code> (これらはともにキーワードです) を取りうる値とする論理型を持っています。どんな値でも以下の規則に基づいて論理値に変換できます。</p> <ol> - <li><code>false</code>、<code>0</code>、空文字列 (<code>""</code>)、<code>NaN</code>、<code>null</code>、および <code>undefined</code> は、すべて <code>false</code> になる</li> - <li>その他の値はすべて <code>true</code> になる</li> + <li><code>false</code>、<code>0</code>、空文字列 (<code>""</code>)、<code>NaN</code>、<code>null</code>、<code>undefined</code> は、すべて <code>false</code> になる。</li> + <li>その他の値はすべて <code>true</code> になる。</li> </ol> -<p><code>Boolean()</code> 関数を使うことで、明示的にこの変換を行うことができます:</p> +<p><code>Boolean()</code> 関数を使うことで、明示的にこの変換を行うことができます。</p> -<pre class="brush: js notranslate">Boolean(''); // false +<pre class="brush: js">Boolean(''); // false Boolean(234); // true </pre> -<p>しかしながら、これはほとんど必要ありません。なぜなら JavaScript は、<code>if</code> 文 (下記参照) の中といった真偽値が期待されるときに、無言でこの変換を行うからです。このような理由から、私たちは時々、真偽値に変換されるとき <code>true</code> または <code>false</code> になる値という意味で、それぞれ "true values" または "false values" と言うことがあります。あるいは、そのような値はそれぞれ "truthy" または "falsy" と呼ばれます。</p> +<p>しかし、これはほとんど必要ありません。 JavaScript は、 <code>if</code> 文の中 (下記参照) のように論理値が期待される場面で、暗黙にこの変換を行うからです。このため、ときどき "true values" または "false values" と言うことがありますが、これは論理値に変換されるときにそれぞれ <code>true</code> または <code>false</code> になる値という意味です。他にも、これらの値はそれぞれ "truthy" または "falsy" と呼ばれることがあります。</p> -<p><code>&&</code> (論理 <em>AND</em>) や <code>||</code> (論理 <em>OR</em>)、<code>!</code> (論理 <em>NOT</em>) などの真偽値演算がサポートされています (下記参照)。</p> +<p><code>&&</code> (論理 <em>AND</em>) や <code>||</code> (論理 <em>OR</em>)、<code>!</code> (論理 <em>NOT</em>) などの論理演算がサポートされています (下記参照)。</p> -<h2 id="Variables" name="Variables">変数</h2> +<h2 id="Variables">変数</h2> -<p>JavaScript における新しい変数は <code><a href="/ja/docs/Web/JavaScript/Reference/Statements/let">let</a></code>、<code><a href="/ja/docs/Web/JavaScript/Reference/Statements/const">const</a></code>、<code><a href="/ja/docs/Web/JavaScript/Reference/Statements/var" title="JavaScript/Reference/Statements/var">var</a></code> の 3 つのキーワードのいずれかを使用して宣言します。</p> +<p>JavaScript では、新しい変数を宣言するのに <code><a href="/ja/docs/Web/JavaScript/Reference/Statements/let">let</a></code>、<code><a href="/ja/docs/Web/JavaScript/Reference/Statements/const">const</a></code>、<code><a href="/ja/docs/Web/JavaScript/Reference/Statements/var">var</a></code> の 3 つのキーワードのいずれかを使用します。</p> -<p><strong><code>let</code></strong> は、ブロックレベルの変数を宣言できます。宣言した変数は、変数を<em>包含する</em>関数ブロックから使用できます。</p> +<p><strong><code>let</code></strong> は、ブロックレベルの変数を宣言できます。宣言した変数は、変数を包含する<em>ブロック</em>から使用できます。</p> -<pre class="brush: js notranslate">let a; +<pre class="brush: js">let a; let name = 'Simon'; </pre> -<p>以下の例は、<code><strong>let</strong></code> で宣言した変数のスコープを示しています:</p> +<p>以下の例は、<code><strong>let</strong></code> で宣言した変数のスコープを示しています。</p> -<pre class="brush: js notranslate">// ここでは myLetVariable が *見えません* +<pre class="brush: js">// ここでは myLetVariable が *見えません* for (let myLetVariable = 0; myLetVariable < 5; myLetVariable++) { // ここだけで myLetVariable が見えます } // ここでは myLetVariable が *見えません* + </pre> -<p><code><strong>const</strong></code> は、変更を意図しない変数を宣言できます。宣言した変数は、変数を<em>宣言した</em>関数ブロックから使用できます。</p> +<p><code><strong>const</strong></code> は、値を変更することを意図しない変数を宣言することができます。宣言した変数は、変数を宣言した<em>ブロック</em>から使用できます。</p> -<pre class="brush: js notranslate">const Pi = 3.14; // 変数 Pi を設定 -Pi = 1; // 不変の変数は変更できないため、エラーが発生します</pre> +<pre class="brush: js">const Pi = 3.14; // 変数 Pi を設定 +Pi = 1; // 定数の変数は変更できないため、エラーが発生します</pre> -<p><code><strong>var</strong></code> は、もっとも一般的な宣言キーワードです。こちらは、他の 2 つのキーワードのような制約がありません。これは、伝統的に JavaScript で変数を宣言する唯一の方法であったためです。<strong><code>var</code></strong> キーワードで宣言した変数は、変数を<em>宣言した</em>関数ブロックから使用できます。</p> +<p><code><strong>var</strong></code> は、もっとも一般的な宣言キーワードです。こちらは、他の 2 つのキーワードのような制約がありません。これは、伝統的に JavaScript で変数を宣言する唯一の方法であったためです。 <strong><code>var</code></strong> キーワードで宣言した変数は、変数を宣言した<em>関数</em>から使用できます。</p> -<pre class="brush: js notranslate">var a; +<pre class="brush: js">var a; var name = 'Simon';</pre> -<p>以下の例は、<strong><code>var</code></strong> で宣言した変数のスコープを示しています:</p> +<p>以下の例は、 <strong><code>var</code></strong> で宣言した変数のスコープを示しています。</p> -<pre class="brush: js notranslate">// ここでは myVarVariable が *見えます* +<pre class="brush: js">// ここでは myVarVariable が *見えます* for (var myVarVariable = 0; myVarVariable < 5; myVarVariable++) { // myVarVariable は関数全体で見えます @@ -220,67 +243,67 @@ for (var myVarVariable = 0; myVarVariable < 5; myVarVariable++) { // ここでは myVarVariable が *見えます* </pre> -<p>もし値を代入しないで変数を宣言すると、その型は <code>undefined</code> になります。</p> +<p>値を代入せずに変数を宣言すると、その型は <code>undefined</code> になります。</p> -<p>Java など他の言語との重要な相違点は、JavaScript ではブロックがスコープを持たず、関数のみがスコープを持つことです。よって、変数が複合文内 (例えば <code>if</code> 制御構造の内部) で <code>var</code> を用いて定義された場合でも、その変数は関数全体でアクセス可能です。ただし ECMAScript 2015 より、<code><a href="/ja/docs/Web/JavaScript/Reference/Statements/let">let</a></code> および <code><a href="/ja/docs/Web/JavaScript/Reference/Statements/const">const</a></code> 宣言でブロックスコープの変数を作成できます。</p> +<p>Java など他の言語との重要な相違点は、 JavaScript ではブロックがスコープを持たないことです。関数のみがスコープを持ちます。よって、変数が複合文内 (例えば <code>if</code> 制御構造の内部) で <code>var</code> を用いて定義された場合でも、その変数は関数全体でアクセス可能です。ただし ECMAScript 2015 より、<code><a href="/ja/docs/Web/JavaScript/Reference/Statements/let">let</a></code> および <code><a href="/ja/docs/Web/JavaScript/Reference/Statements/const">const</a></code> 宣言でブロックスコープの変数を作成することができます。</p> -<h2 id="Operators" name="Operators">演算子</h2> +<h2 id="Operators">演算子</h2> -<p>JavaScript の算術演算子は、<code>+</code>、<code>-</code>、<code>*</code>、<code>/</code>、そして剰余演算子の <code>%</code> (<a href="/ja/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Remainder_%28%29">モジュロと同じです</a>) です。値は <code>=</code> を使って代入されます。また <code>+=</code> や <code>-=</code> のような複合代入文もあります。これらは <code>x = x <em>演算子</em> y</code> と展開できるものです。</p> +<p>JavaScript の算術演算子は、<code>+</code>、<code>-</code>、<code>*</code>、<code>/</code>、そして剰余演算子の <code>%</code> (<a href="/ja/docs/Web/JavaScript/Reference/Operators#remainder_%28%29">モジュロと同じです</a>) です。値は <code>=</code> を使って代入されます。また <code>+=</code> や <code>-=</code> のような複合代入文もあります。これらは <code>x = x <em>演算子</em> y</code> と展開できるものです。</p> -<pre class="brush: js notranslate">x += 5; +<pre class="brush: js">x += 5; x = x + 5; </pre> <p><code>++</code> や <code>--</code> を使ってインクリメントやデクリメントできます。これらは前置あるいは後置演算子として使うことができます。</p> -<p><a href="/ja/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Addition" title="JavaScript/Reference/Operators/String_Operators"><code>+</code> 演算子</a> は文字列の結合もします:</p> +<p><a href="/ja/docs/Web/JavaScript/Reference/Operators#addition"><code>+</code> 演算子</a>は文字列の結合も行います。</p> -<pre class="brush: js notranslate">'hello' + ' world'; // "hello world" +<pre class="brush: js">'hello' + ' world'; // "hello world" </pre> -<p>文字列を数字 (や他の値) に足すと、すべてのものはまず最初に文字列に変換されます。このことはミスを誘うかもしれません:</p> +<p>文字列を数字 (や他の値) に足すと、すべてのものが最初に文字列に変換されます。このことはミスを誘うかもしれません。</p> -<pre class="brush: js notranslate">'3' + 4 + 5; // "345" +<pre class="brush: js">'3' + 4 + 5; // "345" 3 + 4 + '5'; // "75" </pre> <p>空文字列を足すのは、何かを文字列に変換する便利な方法です。</p> -<p>JavaScript における <a href="/ja/docs/Web/JavaScript/Reference/Operators/Comparison_Operators" title="JavaScript/Reference/Operators/Comparison_Operators">比較</a> は、<code><</code> や <code>></code>、<code><=</code>、<code>>=</code> を使ってすることができます。これらは文字列と数値のどちらでも機能します。等価性はちょっと明快ではありません。二重イコール演算子は、異なる型を与えると{{原語併記("型強制", "type coercion")}} を行います。これは時に面白い結果を返します:</p> +<p>JavaScript における <a href="/ja/docs/Web/JavaScript/Reference/Operators">比較</a> は、<code><</code> や <code>></code>、<code><=</code>、<code>>=</code> を使って行うことができます。これらは文字列と数値のどちらでも機能します。等価性はちょっと明快ではありません。二重イコール演算子は、異なる型を与えると型強制を行います。これは時に面白い結果を返します。</p> -<pre class="brush: js notranslate">123 == '123'; // true +<pre class="brush: js">123 == '123'; // true 1 == true; // true </pre> -<p>型強制を防いで厳密な比較を行うようにする場合は、三重イコール演算子を使います:</p> +<p>型強制を防いで厳密な比較を行うようにする場合は、三重イコール演算子を使います。</p> -<pre class="brush: js notranslate">123 === '123'; // false +<pre class="brush: js">123 === '123'; // false 1 === true; // false </pre> <p><code>!=</code> と <code>!==</code> 演算子もあります。</p> -<p>JavaScript は <a href="/ja/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators" title="JavaScript/Reference/Operators/Bitwise_Operators">ビット演算子</a> も持っています。使いたいなら、ちゃんとありますよ。</p> +<p>JavaScript は <a href="/ja/docs/Web/JavaScript/Reference/Operators">ビット演算子</a> も持っています。使いたいなら、ちゃんとありますよ。</p> -<h2 id="Control_structures" name="Control_structures">制御構造</h2> +<h2 id="Control_structures">制御構造</h2> -<p>JavaScript は C 言語ファミリーの他の言語とよく似た制御構造セットを持っています。条件文は <code>if</code> と <code>else</code> でサポートされています。必要ならこれらを連鎖させることもできます:</p> +<p>JavaScript は C 言語ファミリーの他の言語とよく似た制御構造セットを持っています。条件文は <code>if</code> と <code>else</code> でサポートされています。必要ならこれらを連鎖させることもできます。</p> -<pre class="brush: js notranslate">var name = 'kittens'; -if (name == 'puppies') { +<pre class="brush: js">var name = 'kittens'; +if (name === 'puppies') { name += ' woof'; -} else if (name == 'kittens') { +} else if (name === 'kittens') { name += ' meow'; } else { name += '!'; } -name == 'kittens meow'; +name === 'kittens meow'; </pre> -<p>JavaScript は <code>while</code> ループと <code>do-while</code> ループを持っています。1 つ目は普通のループ処理に適しており、2 つ目はループの本体が少なくとも 1 回は実行されるようにしたいときのループです:</p> +<p>JavaScript は <code>while</code> ループと <code>do-while</code> ループを持っています。1 つ目は普通のループ処理に適しており、2 つ目はループの本体が少なくとも 1 回は実行されるようにしたいときのループです。</p> -<pre class="brush: js notranslate">while (true) { +<pre class="brush: js">while (true) { // 無限ループ! } @@ -290,45 +313,45 @@ do { } while (inputIsNotValid(input)); </pre> -<p>JavaScript の <a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for"><code>for</code> ループ</a>は C や Java のそれと同じです。これはループの制御情報を 1 行で与えることができます。</p> +<p>JavaScript の <a href="/ja/docs/Web/JavaScript/Reference/Statements/for"><code>for</code> ループ</a>は C や Java のそれと同じです。これはループの制御情報を 1 行で与えることができます。</p> -<pre class="brush: js notranslate">for (var i = 0; i < 5; i++) { +<pre class="brush: js">for (var i = 0; i < 5; i++) { // 5 回実行されます } </pre> -<p>JavaScript にはこの他に、特徴的な for ループが 2 つあります。ひとつは <a href="/ja/docs/Web/JavaScript/Reference/Statements/for...of"><code>for</code>...<code>of</code></a> です:</p> +<p>JavaScript にはこの他に、特徴的な for ループが 2 つあります。ひとつは <a href="/ja/docs/Web/JavaScript/Reference/Statements/for...of"><code>for</code>...<code>of</code></a> です。</p> -<pre class="brush: js notranslate">for (let value of array) { +<pre class="brush: js">for (let value of array) { // 値に関する処理 } </pre> -<p>もうひとつは <a href="/ja/docs/Web/JavaScript/Reference/Statements/for...in"><code>for</code>...<code>in</code></a> です:</p> +<p>もうひとつは <a href="/ja/docs/Web/JavaScript/Reference/Statements/for...in"><code>for</code>...<code>in</code></a> です。</p> -<pre class="brush: js notranslate">for (let property in object) { +<pre class="brush: js">for (let property in object) { // オブジェクトのプロパティに関する処理 } </pre> -<p><code>&&</code> と <code>||</code> 演算子は、1 つ目のオペランドによって 2 つ目のオペランドを評価するか否かが決まる{{原語併記("短絡論理", "short-circuit logic")}} を用いています。これはあるオブジェクトの属性にアクセスする前に、それが null オブジェクトかをチェックするのに便利です:</p> +<p><code>&&</code> と <code>||</code> 演算子は、1 つ目のオペランドによって 2 つ目のオペランドを評価するか否かが決まる短絡論理 (short-circuit logic) を採用しています。これはあるオブジェクトの属性にアクセスする前に、それが null オブジェクトかをチェックするのに便利です。</p> -<pre class="brush: js notranslate">var name = o && o.getName(); +<pre class="brush: js">var name = o && o.getName(); </pre> -<p>あるいは値の格納にも便利です (falsy な値は無効であるとき):</p> +<p>あるいは値の格納にも便利です (falsy な値は無効であるとき)。</p> -<pre class="brush: js notranslate">var name = cachedName || (cachedName = getName()); +<pre class="brush: js">var name = cachedName || (cachedName = getName()); </pre> -<p>JavaScript はワンライン条件文のための三項演算子を持っています:</p> +<p>JavaScript は条件による式のための三項演算子を持っています。</p> -<pre class="brush: js notranslate">var allowed = (age > 18) ? 'yes' : 'no'; +<pre class="brush: js">var allowed = (age > 18) ? 'yes' : 'no'; </pre> -<p><code>switch</code> 文はある数値や文字列を元にした複数分岐に使われます:</p> +<p><code>switch</code> 文はある数値や文字列を元にした複数分岐に使われます。</p> -<pre class="brush: js notranslate">switch (action) { +<pre class="brush: js">switch (action) { case 'draw': drawIt(); break; @@ -340,10 +363,10 @@ do { } </pre> -<p>もし <code>break</code> 文を入れなければ、処理は次の段階へ{{原語併記("フォールスルー", "fall through")}} します。この動作が望むものであることは非常にまれでしょう ― 事実、もしそれが本当に意図するものならば、デバッグの補助として故意のフォールスルーをコメントで明確にラベリングするだけの価値があるでしょう:</p> +<p>もし <code>break</code> 文を入れなければ、処理は次の段階へ「落下」 (fall through) します。この動作が望むものであることはまれでしょう — 実際にそれが意図的な落下であれば、デバッグの助けになるようにコメントでラベル付しておくといいでしょう。</p> -<pre class="brush: js notranslate">switch (a) { - case 1: // フォールスルー +<pre class="brush: js">switch (a) { + case 1: // 落下 case 2: eatIt(); break; @@ -352,9 +375,9 @@ do { } </pre> -<p>default 節は省略できます。必要ならば、switch 部と case 部のどちらにも式を置くことができます。比較はこれら 2 つの間で <code>===</code> 演算子を使って行われます:</p> +<p>default 節は省略できます。必要ならば、switch 部と case のどちらにも式を置くことができます。比較はこれら 2 つの間で <code>===</code> 演算子を使って行われます。</p> -<pre class="brush: js notranslate">switch (1 + 3) { +<pre class="brush: js">switch (1 + 3) { case 2 + 2: yay(); break; @@ -363,9 +386,9 @@ do { } </pre> -<h2 id="Objects" name="Objects">オブジェクト</h2> +<h2 id="Objects">オブジェクト</h2> -<p>JavaScript のオブジェクトは、名前と値のペアの単純なコレクションであると考えることができます。これは以下のものに似ています:</p> +<p>JavaScript のオブジェクトは、名前と値のペアの単純なコレクションであると考えることができます。これは以下のものに似ています。</p> <ul> <li>Python の辞書型</li> @@ -375,27 +398,27 @@ do { <li>PHP の連想配列</li> </ul> -<p>このデータ構造が幅広く使われているという事実は、この構造の万能性の証拠でしょう。JavaScript において (コアデータ型を除いた) すべてのものはオブジェクトなので、どんな JavaScript プログラムも自然と非常に多くのハッシュテーブルのルックアップ (検索) を伴います。良いことにそれがとても速いのです!</p> +<p>このデータ構造がこれほど広く使われているのは、その汎用性の高さを物語っています。 JavaScript では (コアデータ型を除いて) すべてのものはオブジェクトなので、どんな JavaScript のプログラムでは当然、ハッシュテーブルの参照が大量に行われます。ハッシュテーブルが高速なのは良いことですね。</p> <p>「名前」部は JavaScript における文字列であるのに対し、値は JavaScript のどんな値でも ― さらなるオブジェクトでも ― 構いません。この仕様が任意の複雑なデータ構造を作ることを可能にしています。</p> -<p>空のオブジェクトを生成する 2 つの基本的な方法があります:</p> +<p>空のオブジェクトを生成する 2 つの基本的な方法があります。</p> -<pre class="brush: js notranslate">var obj = new Object(); +<pre class="brush: js">var obj = new Object(); </pre> -<p>そして:</p> +<p>そして、</p> -<pre class="brush: js notranslate">var obj = {}; +<pre class="brush: js">var obj = {}; </pre> <p>これらは意味的に等価です。2 つ目はオブジェクトリテラル構文と呼ばれ、こちらの方がより便利です。オブジェクトリテラル構文は JSON 書式の中核でもあり、こちらを採用するべきです。</p> -<p>オブジェクトリテラル構文はオブジェクトをそっくりそのまま初期化するのに使えます:</p> +<p>オブジェクトリテラル構文はオブジェクト全体を初期化するのに使えます。</p> -<pre class="brush: js notranslate">var obj = { +<pre class="brush: js">var obj = { name: 'Carrot', - for: 'Max', // 'for' は予約語であり、代わりに '_for' を使用します + _for: 'Max', // 'for' は予約語であるため、代わりに '_for' を使用します details: { color: 'orange', size: 12 @@ -403,15 +426,15 @@ do { }; </pre> -<p>属性へのアクセスは同時に連鎖させることができます:</p> +<p>属性へのアクセスは同時に連鎖させることができます。</p> -<pre class="brush: js notranslate">obj.details.color; // orange +<pre class="brush: js">obj.details.color; // orange obj['details']['size']; // 12 </pre> -<p>以下の例ではオブジェクトのプロトタイプである <code>Person</code> と、プロトタイプのインスタンスである <code>you</code> を生成しています。</p> +<p>以下の例ではオブジェクトのプロトタイプ (<code>Person</code>) と、プロトタイプのインスタンス (<code>you</code>) を生成しています。</p> -<pre class="brush: js notranslate">function Person(name, age) { +<pre class="brush: js">function Person(name, age) { this.name = name; this.age = age; } @@ -421,94 +444,97 @@ var you = new Person('You', 24); // "You" という名前で、年齢が 24 歳の新たな Person を作成しました </pre> -<p><strong>一度作ってしまえば</strong>、オブジェクトのプロパティには下記の 2 つの方法のいずれかで再びアクセスすることができます:</p> +<p><strong>一度作ってしまえば</strong>、オブジェクトのプロパティには下記の 2 つの方法のいずれかで再びアクセスすることができます。</p> -<pre class="brush: js notranslate"><code class="language-js"><span class="comment token">// ドット記法</span></code> +<pre class="brush: js">// ドット記法 obj.name = 'Simon'; var name = obj.name; </pre> <p>そして...</p> -<pre class="brush: js line-numbers language-js notranslate"><code class="language-js"><span class="comment token">// 括弧記法</span> -obj<span class="punctuation token">[</span><span class="string token">'name'</span><span class="punctuation token">]</span> <span class="operator token">=</span> <span class="string token">'Simon'</span><span class="punctuation token">;</span> -<span class="keyword token">var</span> name <span class="operator token">=</span> obj<span class="punctuation token">[</span><span class="string token">'name'</span><span class="punctuation token">]</span><span class="punctuation token">;</span> -<span class="comment token">// 変数をキー定義に使用できる</span> -<span class="keyword token">var</span> user <span class="operator token">=</span> <span class="function token">prompt</span><span class="punctuation token">(</span><span class="string token">'what is your key?'</span><span class="punctuation token">)</span> -obj<span class="punctuation token">[</span>user<span class="punctuation token">]</span> <span class="operator token">=</span> <span class="function token">prompt</span><span class="punctuation token">(</span><span class="string token">'what is its value?'</span><span class="punctuation token">)</span></code></pre> +<pre class="brush: js">// ブラケット記法 +obj['name'] = 'Simon'; +var name = obj['name']; +// 変数をキー定義に使用できる +var user = prompt('what is your key?') +obj[user] = prompt('what is its value?') +</pre> -<p>これらもまた意味的に等価です。2 つ目の方法はプロパティの名前を文字列として与えるという利点があり、つまりその名前を実行時に計算できることを意味します。ただ、この方法を用いると JavaScript エンジンや minifier による最適化が適用されなくなります。またこの方法は、<a href="/ja/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords" title="JavaScript/Reference/Reserved_Words">予約語</a> と同じ名前のプロパティを設定したり取得したりするのに使うことができます:</p> +<p>これらもまた意味的に等価です。2 つ目の方法はプロパティの名前を文字列として与えるという利点があり、つまりその名前を実行時に計算できることを意味します。ただ、この方法を用いると JavaScript エンジンや minifier による最適化が適用されなくなります。またこの方法は、<a href="/ja/docs/Web/JavaScript/Reference/Lexical_grammar#keywords">予約語</a> と同じ名前のプロパティを設定したり取得したりするのに使うことができます。</p> -<pre class="brush: js notranslate">obj.for = 'Simon'; // 構文エラー。'for' が予約語であるため +<pre class="brush: js">obj.for = 'Simon'; // 構文エラー。'for' が予約語であるため obj['for'] = 'Simon'; // うまく動きます </pre> -<div class="note">ECMAScript 第 5 版より、予約語をオブジェクトのプロパティ名として"そのまま"使用できます。つまりオブジェクトリテラルの定義時に引用符で"括る"必要ありません。ES5 の<a href="http://es5.github.io/#x7.6.1">仕様</a>を確認してください。</div> +<div class="note"> +<p><strong>注:</strong> ECMAScript 第 5 版より、予約語をオブジェクトのプロパティ名として「そのまま」使用できます。つまりオブジェクトリテラルの定義時に引用符で「括る」必要はありません。 ES5 の<a href="https://es5.github.io/#x7.6.1">仕様</a>を確認してください。</p> +</div> -<p>オブジェクトやプロトタイプについて、詳しくは <a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype">Object.prototype</a> をご覧ください。オブジェクトプロトタイプやオブジェクトプロトタイプチェーンの説明は、<a href="/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain">継承とプロトタイプチェーン</a> をご覧ください。</p> +<p>オブジェクトやプロトタイプについて、詳しくは <a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Object">Object.prototype</a> をご覧ください。オブジェクトプロトタイプやオブジェクトプロトタイプチェーンの説明は、<a href="/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain">継承とプロトタイプチェーン</a> をご覧ください。</p> <div class="note"> -<p>ECMAScript 2015 より、オブジェクトのキーが括弧記法を使った変数で定義できるようになりました。<code>{[phoneType]: 12345}</code> が単に <code>var userPhone = {}; userPhone[phoneType] = 12345</code> の代わりにできます。</p> +<p>ECMAScript 2015 より、オブジェクトのキーがブラケット記法を使った変数で定義できるようになりました。 <code>{[phoneType]: 12345}</code> が <code>var userPhone = {}; userPhone[phoneType] = 12345</code> の代わりにできます。</p> </div> -<h2 id="Arrays" name="Arrays">配列</h2> +<h2 id="Arrays">配列</h2> -<p>JavaScript における配列は、実はオブジェクトの特殊型です。普通のオブジェクトとほとんど同じように働きます (数字のプロパティは当然 <code>[]</code> の構文でのみアクセスできます) が、しかし配列は '<code>length</code>' という魔法のプロパティを持っています。これは常に配列の一番大きな添字より 1 大きい値を取ります。</p> +<p>JavaScript における配列は、実はオブジェクトの特殊型です。普通のオブジェクトとほとんど同じように働きます (数値のプロパティは当然 <code>[]</code> の構文でのみアクセスできます) が、しかし配列は '<code>length</code>' という魔法のプロパティを持っています。これは常に配列の一番大きな添字より 1 大きい値を取ります。</p> -<p>配列を生成する方法のひとつは以下の通り:</p> +<p>配列を生成する方法のひとつは以下の通りです。</p> -<pre class="brush: js notranslate">var a = new Array(); +<pre class="brush: js">var a = new Array(); a[0] = 'dog'; a[1] = 'cat'; a[2] = 'hen'; a.length; // 3 </pre> -<p>より便利な書き方は配列リテラルを使うことです:</p> +<p>より便利な書き方は配列リテラルを使うことです。</p> -<pre class="brush: js notranslate">var a = ['dog', 'cat', 'hen']; +<pre class="brush: js">var a = ['dog', 'cat', 'hen']; a.length; // 3 </pre> -<p><code>array.length</code> は必ずしも配列中の要素の数ではないことに注意してください。以下の例を考えてみましょう:</p> +<p><code>array.length</code> は必ずしも配列中の要素の数ではないことに注意してください。以下の例を考えてみましょう。</p> -<pre class="brush: js notranslate">var a = ['dog', 'cat', 'hen']; +<pre class="brush: js">var a = ['dog', 'cat', 'hen']; a[100] = 'fox'; a.length; // 101 </pre> <p>思い出してください ― 配列の長さは一番大きな添字より 1 大きい値です。</p> -<p>もし存在しない配列の添字を要求すると、<code>undefined</code> が得られます:</p> +<p>もし存在しない配列の添字を要求すると、<code>undefined</code> が得られます。</p> -<pre class="brush: js notranslate">typeof a[90]; // undefined +<pre class="brush: js">typeof a[90]; // undefined </pre> -<p>上記の <code>[]</code> と <code>length</code> を考慮に入れれば、以下の <code>for</code> ループを使って配列を繰り返すことができます:</p> +<p>上記の <code>[]</code> と <code>length</code> を考慮に入れれば、以下の <code>for</code> ループを使って配列を反復処理することができます。</p> -<pre class="brush: js notranslate">for (var i = 0; i < a.length; i++) { +<pre class="brush: js">for (var i = 0; i < a.length; i++) { // a[i] について何かする } </pre> -<p>ES2015では配列のような iterable オブジェクト用に、より正確な <a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for...of"><code>for</code>...<code>of</code></a> ループが導入されました:</p> +<p>ES2015 では配列のような反復可能オブジェクト向けに、より正確な <a href="/ja/docs/Web/JavaScript/Reference/Statements/for...of"><code>for</code>...<code>of</code></a> ループが導入されました。</p> -<pre class="brush:js line-numbers language-js notranslate"><code class="language-js"><span class="keyword token">for</span> <span class="punctuation token">(</span><span class="keyword token">const</span> currentValue <span class="keyword token">of</span> a<span class="punctuation token">)</span> <span class="punctuation token">{</span> - <span class="comment token">// currentValue</span>(現在の値)で何かをする -<span class="punctuation token">}</span></code></pre> +<pre class="brush: js">for (const currentValue of a) { + // currentValue (現在の値) で何かをする +}</pre> -<p><code><a href="/ja/docs/Web/JavaScript/Reference/Statements/for...in" title="JavaScript/Reference/Statements/for...in">for</a></code><a href="/ja/docs/Web/JavaScript/Reference/Statements/for...in" title="JavaScript/Reference/Statements/for...in">...</a><code><a href="/ja/docs/Web/JavaScript/Reference/Statements/for...in" title="JavaScript/Reference/Statements/for...in">in</a></code> ループを使用して配列を繰り返すすることもできます。ただし、もし誰かが <code>Array.prototype</code> に新しいプロパティを追加していたら、それらもこのループで繰り返されてしまうので注意してください。よって、この方法は配列に対しては "推奨しません"。</p> +<p><a href="/ja/docs/Web/JavaScript/Reference/Statements/for...in"><code>for</code>...<code>in</code></a> ループを使用して配列を反復処理することもできます。ただし、もし誰かが <code>Array.prototype</code> に新しいプロパティを追加していたら、このループでそれらに対しても反復処理されてしまうので注意してください。よって、この方法は配列に対しては推奨しません。</p> -<p>配列を繰り返すもうひとつの方法が、 ECMAScript 5 で追加された <code><a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">forEach()</a></code> です:</p> +<p>配列を繰り返すもうひとつの方法が、 ECMAScript 5 で追加された <code><a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">forEach()</a></code> です。</p> -<pre class="brush: js notranslate" style="font-size: 14px;">['dog', 'cat', 'hen'].forEach(function(currentValue, index, array) { - // currentValue<code class="language-js">(現在の値)</code> または array[index] について何かする +<pre class="brush: js">['dog', 'cat', 'hen'].forEach(function(currentValue, index, array) { + // currentValue (現在の値) または array[index] について何かする }); </pre> -<p>配列に要素を追加したいなら、このようにするのがもっともシンプルです:</p> +<p>配列に要素を追加したいなら、このようにするのがもっともシンプルです。</p> -<pre class="brush: js notranslate">a.push(item);</pre> +<pre class="brush: js">a.push(item);</pre> <p>配列には多くのメソッドがついてきます。<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Array">配列のメソッドに関するドキュメント</a> もご覧ください。</p> @@ -571,33 +597,33 @@ a.length; // 101 </tbody> </table> -<h2 id="Functions" name="Functions">関数</h2> +<h2 id="Functions">関数</h2> -<p>オブジェクトとともに、関数は JavaScript を理解するうえで核となる構成要素です。もっとも基本的な関数は極めてシンプルです:</p> +<p>オブジェクトとともに、関数は JavaScript を理解するうえで核となる構成要素です。もっとも基本的な関数は極めてシンプルです。</p> -<pre class="brush: js notranslate">function add(x, y) { +<pre class="brush: js">function add(x, y) { var total = x + y; return total; } </pre> -<p>これは基本的な関数を例示しています。JavaScript の関数は 0 以上の名前のついた引数を取ることができます。関数の本体は好きなだけたくさんの文を含ませることができ、またその関数内で局所的な変数を宣言することができます。<code>return</code> 文は好きなときに関数を終了し値を返すために使うことができます。もし <code>return</code> 文が使われなかったら (あるいは値をつけない空の return が使われたら)、JavaScript は <code>undefined</code> を返します。</p> +<p>これは基本的な関数を例示しています。JavaScript の関数は 0 以上の名前のついた引数を取ることができます。関数の本体は好きなだけたくさんの文を含ませることができ、またその関数内で局所的な変数を宣言することができます。<code>return</code> 文は好きなときに関数を終了し値を返すために使うことができます。もし return 文が使われなかったら (あるいは値を持たない空の return が使われたら)、JavaScript は <code>undefined</code> を返します。</p> -<p>実のところ、名前のついた引数はガイドラインのようなもの以外の何物でもありません。あなたは期待された引数を渡さずに関数を呼ぶことができます。その場合引数には <code>undefined</code> がセットされます。</p> +<p>名前のついた引数は、何よりもガイドラインのようなものです。期待された引数を渡さずに関数を呼び出すことができます。その場合、引数には <code>undefined</code> が設定されます。</p> -<pre class="brush: js notranslate">add(); // NaN +<pre class="brush: js">add(); // NaN // undefined では加算を実行できない </pre> -<p>あなたはまた、関数が期待しているより多くの引数を渡すこともできます:</p> +<p>また、関数が期待するより多くの引数を渡すこともできます。</p> -<pre class="brush: js notranslate">add(2, 3, 4); // 5 +<pre class="brush: js">add(2, 3, 4); // 5 // 第 1、第 2 引数を加算。4 は無視される </pre> -<p>これは少し馬鹿げているように見えるかもしれませんが、関数はその本体の中で <a href="/ja/docs/Web/JavaScript/Reference/Functions/arguments" title="JavaScript/Reference/Functions_and_function_scope/arguments"><code>arguments</code></a> と呼ばれる追加の変数を利用することができます。これはその関数へ渡されたすべての値を保持する配列のようなオブジェクトです。さあ、add 関数を好きなだけたくさんの値をとれるよう書き直してみましょう:</p> +<p>これは少し馬鹿げているように見えるかもしれませんが、関数はその本体の中で <a href="/ja/docs/Web/JavaScript/Reference/Functions/arguments"><code>arguments</code></a> と呼ばれる追加の変数を利用することができます。これはその関数へ渡されたすべての値を保持する配列のようなオブジェクトです。 add 関数を好きなだけたくさんの値をとれるよう書き直してみましょう。</p> -<pre class="brush: js notranslate">function add() { +<pre class="brush: js">function add() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; @@ -608,9 +634,9 @@ a.length; // 101 add(2, 3, 4, 5); // 14 </pre> -<p>しかしこれは <code>2 + 3 + 4 + 5</code> と書くより使い勝手がいいものではまったくありません。平均を取る関数を作ってみましょう:</p> +<p>しかしこれは <code>2 + 3 + 4 + 5</code> と書くより使い勝手がいいものではまったくありません。平均を取る関数を作ってみましょう。</p> -<pre class="brush: js notranslate">function avg() { +<pre class="brush: js">function avg() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; @@ -621,28 +647,24 @@ add(2, 3, 4, 5); // 14 avg(2, 3, 4, 5); // 3.5 </pre> -<p>この関数はかなり便利ですが、やや冗長にみえます。コードを減らすために、 <a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/rest_parameters">Rest パラメーター記法</a>で引数配列の使用を置き換えることを検討できます。この方法では、コードを最小限にしながら任意の数の引数を関数に渡すことができます。<strong>Restパラメーター演算子</strong>は <strong>...変数</strong>の形式で、関数宣言内で使用します。また、これは変数内に、関数を呼び出したときに未取得の引数すべてのリストが含まれます。また、変数内の値を返すための <strong>for</strong> ループを <strong>for...of</strong> ループに置き換えます。</p> +<p>これはとても便利ですが、少し冗長な印象を受けます。このコードをもう少し減らすために、引数配列の代わりに<a href="/ja/docs/Web/JavaScript/Reference/Functions/rest_parameters">残余引数構文</a>を使ってみましょう。この方法では、コードを最小限に保ちながら、関数に任意の数の引数を渡すことができます。<strong>残余引数演算子</strong>は、関数の引数リストで <strong>...変数</strong> という書式で使用され、その変数の中に、関数が呼び出されたときに取得されなかった引数のリストをすべて含めることができます。また、 <strong>for</strong> ループを <strong>for...of</strong> ループに置き換えて、変数内の値を返すようにします。</p> -<pre class="brush: js notranslate">function avg(...args) { - var sum = 0; - for (let value of args) { - sum += value; - } - return sum / args.length; +<pre class="brush: js">function avg(...args) { + var sum = 0; + for (let value of args) { + sum += value; + } + return sum / args.length; } avg(2, 3, 4, 5); // 3.5 </pre> -<div class="note"> -<div class="syntaxbox">上記のコードで変数 <strong>args</strong> は、関数に渡されたすべての値を保持します。<br> -<br> -関数宣言に rest パラメーターを置くと常に、その前方ではなく<em>後方</em>にある、すべての引数を保存することへの注意が重要です。</div> +<p>上記のコードで変数 <strong>args</strong> は、関数に渡されたすべての値が格納されています。</p> -<div class="syntaxbox">つまり例えば <em>function</em> <em>avg(</em><strong>firstValue, </strong><em>...args</em><strong><em>)</em></strong> は、関数に渡した最初の値が変数 <strong>firstValue</strong> に、残りの引数が <strong>args</strong> に保存されます。この関数はかなり便利ですが、新たな問題を提示しています。この <code>avg()</code> 関数はコンマ区切りのリストを引数に取りますが、もし配列の平均を知りたいときにはどうしたらいいでしょう? あなたは単純に関数を以下のように書き直すこともできます:</div> -</div> +<p>注意すべき点は、関数宣言の中に残余引数演算子が置かれている場合、宣言の<em>後</em>のすべての引数が格納されますが、宣言の前の引数は格納されないということです。すなわち、 <em>function avg(<strong>firstValue, </strong>...args)</em> では、関数に渡された最初の値が変数 <strong>firstValue</strong> に格納され、残りの引数が <strong>args</strong> に格納されます。これも便利な言語機能のひとつですが、新たな問題が発生しました。 <code>avg()</code> 関数はカンマで区切られた引数のリストを受け取りますが、配列の平均値を求めたい場合はどうすればよいのでしょうか。この関数を次のように書き換えればよいのです。</p> -<pre class="brush: js notranslate">function avgArray(arr) { +<pre class="brush: js">function avgArray(arr) { var sum = 0; for (var i = 0, j = arr.length; i < j; i++) { sum += arr[i]; @@ -653,22 +675,22 @@ avg(2, 3, 4, 5); // 3.5 avgArray([2, 3, 4, 5]); // 3.5 </pre> -<p>しかし私たちがすでに作った関数を再利用できた方がいいですよね。幸運なことに、JavaScript は関数オブジェクトの {{jsxref("Function.apply", "apply()")}} メソッドを使うことで、引数に任意の配列をつけて呼ぶことができます。</p> +<p>しかし、せっかく作った関数を再利用できたらいいですよね。幸い JavaScript では、任意の関数オブジェクトの {{jsxref("Function.apply", "apply()")}} メソッドを使って、任意の配列を引数として関数を呼び出すことができます。</p> -<pre class="brush: js notranslate">avg.apply(null, [2, 3, 4, 5]); // 3.5 +<pre class="brush: js">avg.apply(null, [2, 3, 4, 5]); // 3.5 </pre> <p><code>apply()</code> の第 2 引数は引数として使う配列です。第 1 引数は後で論じます。このようなことは関数もまたオブジェクトであるという事実を強調します。</p> -<div class="note"> -<p>同じ結果を関数呼び出しの<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_operator">スプレッド演算子</a>でも達成できます。</p> +<p>関数呼び出しで<a href="/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax">スプレッド演算子</a>を使用しても同じ結果を実現できます。</p> -<p>例えば: <code>avg(...numbers)</code></p> -</div> +<p>例: <code>avg(...numbers)</code></p> + +<h3 id="anonymous_functions">無名関数</h3> -<p>JavaScript では{{原語併記("無名関数", "anonymous functions")}} を作ることができます。</p> +<p>JavaScript では無名関数 (anonymous function) — すなわち、名前のない関数を作ることができます。</p> -<pre class="brush: js notranslate">var avg = function() { +<pre class="brush: js">function() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; @@ -677,23 +699,33 @@ avgArray([2, 3, 4, 5]); // 3.5 }; </pre> -<p>これは意味的には <code>function avg()</code> 形式と等価です。これは非常に強力です。あなたは普通は式を置くところならどこにでも完全な関数定義を置くことができるのです。これはあらゆる巧妙なトリックを可能にしています。ここではいくつかの局所変数を ― C のブロックスコープのように ― 「隠す」方法を示します:</p> +<p>しかし、このような無名関数は単独では役に立ちません。 — 名前がなければ、その関数を呼び出す方法がないからです。そのため、実際には、無名関数は他の関数の引数として使われたり、関数を呼び出すために使用することができる変数に直接代入して呼び出し可能にしたりするのが一般的です。</p> -<pre class="brush: js notranslate">var a = 1; -var b = 2; +<pre class="brush: js">var avg = function() { + var sum = 0; + for (var i = 0, j = arguments.length; i < j; i++) { + sum += arguments[i]; + } + return sum / arguments.length; +}; +</pre> -(function() { - var b = 3; - a += b; -})(); +<p>これによって、無名関数を <code>avg()</code> に引数を付けて呼ぶことで呼び出すことが可能になります。 — すなわち、意味的には <code>function avg()</code> という名前付き関数の形を使用して関数を宣言するのと同等になります。</p> + +<p>しかし、変数に代入したり、他の関数の引数として渡されたりしなくても、無名関数が役に立つ方法があります。 JavaScript には、 1 つの式で関数の宣言と起動を同時に行う仕組みがあります。これは <a href="/ja/docs/Glossary/IIFE">IIFE (Immediately invoked function expression)</a> と呼ばれ、無名関数で使用する場合の構文は次のようになります。</p> -a; // 4 -b; // 2 +<pre class="brush: js">(function() { + // … +})(); </pre> +<p>IIFE の詳細については、この入門記事の範囲を越えますが、どのように役立つかについては、<a href="/ja/docs/Web/JavaScript/Closures">クロージャ</a>の記事の<a href="/ja/docs/Web/JavaScript/Closures#emulating_private_methods_with_closures">クロージャでプライベートメソッドを模倣する</a>の節に良い例があります。</p> + +<h3 id="recursive_functions">再帰関数</h3> + <p>JavaScript では関数を再帰的に呼び出すことができます。これは特にブラウザーの DOM などにみられる木構造を取り扱うときに便利でしょう。</p> -<pre class="brush: js notranslate">function countChars(elm) { +<pre class="brush: js">function countChars(elm) { if (elm.nodeType == 3) { // TEXT_NODE return elm.nodeValue.length; } @@ -705,9 +737,9 @@ b; // 2 } </pre> -<p>この例は無名関数に関するある潜在的な問題を際立たせます。名前を持たない関数を再帰呼び出しさせるにはどうしたらよいのでしょう? JavaScript では、名前付き関数式で実現できます。以下のように、名前付き <a href="https://developer.mozilla.org/ja/docs/Glossary/IIFE">IIFEs (Immediately Invoked Function Expressions)</a> を使用できます:</p> +<p>この例は無名関数に関するある潜在的な問題を際立たせます。名前を持たない関数を再帰呼び出しさせるにはどうしたらよいのでしょう? JavaScript では、名前付き関数式で実現できます。以下のように、名前付き <a href="/ja/docs/Glossary/IIFE">IIFE (Immediately Invoked Function Expressions)</a> を使用できます。</p> -<pre class="brush: js notranslate">var charsInBody = (function counter(elm) { +<pre class="brush: js">var charsInBody = (function counter(elm) { if (elm.nodeType == 3) { // TEXT_NODE return elm.nodeValue.length; } @@ -721,15 +753,15 @@ b; // 2 <p>上記のように関数式に与えられた名前は、関数自身のスコープ内でのみ有効です。これはエンジンによる高度な最適化を実現して、結果的に可読性が高いコードになります。この名前はデバッガーやスタックトレースにも表示されますので、デバッグにかかる時間を節約できます。</p> -<p>JavaScript の関数自体が (他のものすべてと同様に) オブジェクトですので、オブジェクトの章で見てきたとおり、プロパティの追加や変更が可能です。</p> +<p>JavaScript の関数自体が (他のものすべてと同様に) オブジェクトですので、オブジェクトの節で見てきたとおり、プロパティの追加や変更が可能です。</p> -<h2 id="Custom_objects" name="Custom_objects">カスタムオブジェクト</h2> +<h2 id="Custom_objects">カスタムオブジェクト</h2> -<div class="note">JavaScript でのオブジェクト指向プログラミングの詳細な論考については、<a href="/ja/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript" title="Introduction_to_Object-Oriented_JavaScript">オブジェクト指向 JavaScript 入門</a> をご覧ください。</div> +<div class="note">JavaScript でのオブジェクト指向プログラミングの詳細な論考については、<a href="/ja/docs/Learn/JavaScript/Objects">オブジェクト指向 JavaScript 入門</a> をご覧ください。</div> -<p>古典的なオブジェクト指向プログラミングにおいて、オブジェクトとはデータとそのデータを操作するメソッドの集まりです。JavaScript は、C++ や Java に見られる class 文を持たない、プロトタイプベースの言語です。(これは、class 文を持つ言語に慣れたプログラマーを混乱させることでしょう) 代わりに、JavaScript は関数をクラスとして用います。ファーストネームとラストネームのフィールドを持つ person オブジェクトを考えてみましょう。その名前を表示させる方法には 2 種類が考えられます: "first last" と "last, first" です。ここまでで論じた関数とオブジェクトを使ってみると、以下のようにデータを表示できるでしょう:</p> +<p>古典的なオブジェクト指向プログラミングにおいて、オブジェクトとはデータとそのデータを操作するメソッドの集まりです。JavaScript は、C++ や Java に見られる class 文を持たない、プロトタイプベースの言語です (これは、 class 文を持つ言語に慣れたプログラマーを混乱させることがあります)。代わりに、 JavaScript は関数をクラスとして用います。ファーストネームとラストネームのフィールドを持つ person オブジェクトを考えてみましょう。その名前を表示させる方法には、 "first last" と "last, first" の 2 種類が考えられます。ここまでで論じた関数とオブジェクトを使ってみると、以下のようにデータを表示できるでしょう。</p> -<pre class="brush: js notranslate">function makePerson(first, last) { +<pre class="brush: js">function makePerson(first, last) { return { first: first, last: last @@ -742,14 +774,14 @@ function personFullNameReversed(person) { return person.last + ', ' + person.first; } -s = makePerson('Simon', 'Willison'); +var s = makePerson('Simon', 'Willison'); personFullName(s); // "Simon Willison" personFullNameReversed(s); // "Willison, Simon" </pre> -<p>これはこれでうまく行きますが、かなり見苦しいですね。グローバルな名前空間にいくつもの関数を作ることになってしまいます。本当にしたいことは関数をオブジェクトにくっつけることです。関数はオブジェクトなので、簡単にできます:</p> +<p>これはこれでうまく行きますが、かなり見苦しいですね。グローバルな名前空間にいくつもの関数を作ることになってしまいます。本当にしたいことは関数をオブジェクトにくっつけることです。関数はオブジェクトなので、簡単にできます。</p> -<pre class="brush: js notranslate">function makePerson(first, last) { +<pre class="brush: js">function makePerson(first, last) { return { first: first, last: last, @@ -762,25 +794,25 @@ personFullNameReversed(s); // "Willison, Simon" }; } -s = makePerson('Simon', 'Willison'); +var s = makePerson('Simon', 'Willison'); s.fullName(); // "Simon Willison" s.fullNameReversed(); // "Willison, Simon" </pre> -<p>おや、まだ見たことがないものがありますね。<code><a href="/ja/docs/Web/JavaScript/Reference/Operators/this" title="JavaScript/Reference/Operators/this">this</a></code> キーワードです。関数内で使われると、<code>this</code> は現在のオブジェクトを参照します。実際に意味するところは関数の呼ばれ方によります。オブジェクト上で <a href="/ja/docs/Web/JavaScript/Reference/Operators/Object_initializer#Accessing_properties" title="JavaScript/Reference/Operators/Member_Operators">ドットの記法や角カッコの記法</a> を使って呼び出すと、そのオブジェクトが <code>this</code> になります。ドット記法を使わずに呼び出すと、<code>this</code> はグローバルオブジェクトを参照します。</p> +<p><code><a href="/ja/docs/Web/JavaScript/Reference/Operators/this">this</a></code> キーワードに注意してください。関数内で使われると、<code>this</code> は現在のオブジェクトを参照します。実際に意味するところは関数の呼び出し方によります。オブジェクト上で<a href="/ja/docs/Web/JavaScript/Reference/Operators/Object_initializer#accessing_properties">ドット記法やブラケット記法</a>を使って呼び出すと、そのオブジェクトが <code>this</code> になります。ドット記法を使わずに呼び出すと、 <code>this</code> はグローバルオブジェクトを参照します。</p> -<p><code>this</code> は失敗の原因になることがよくありますので注意してください。例えば:</p> +<p><code>this</code> は次のように、失敗の原因になることがよくありますので注意してください。</p> -<pre class="brush: js notranslate">s = makePerson('Simon', 'Willison'); +<pre class="brush: js">var s = makePerson('Simon', 'Willison'); var fullName = s.fullName; fullName(); // undefined undefined </pre> <p><code>s.fullName()</code> とせずに <code>fullName()</code> を単独で呼び出すと、<code>this</code> はグローバルオブジェクトに結び付けられます。<code>first</code> や <code>last</code> というグローバル変数はありませんので、それぞれに対して <code>undefined</code> が得られます。</p> -<p>この <code>this</code> キーワードを活用することで、<code>makePerson</code> 関数を改良することができます:</p> +<p>この <code>this</code> キーワードを活用することで、<code>makePerson</code> 関数を改良することができます。</p> -<pre class="brush: js notranslate">function Person(first, last) { +<pre class="brush: js">function Person(first, last) { this.first = first; this.last = last; this.fullName = function() { @@ -793,13 +825,13 @@ fullName(); // undefined undefined var s = new Person('Simon', 'Willison'); </pre> -<p>もう 1 つのキーワード <code><a href="/ja/docs/Web/JavaScript/Reference/Operators/new" title="JavaScript/Reference/Operators/new">new</a></code> が出てきました。<code>new</code> は <code>this</code> と強い関連があります。これは新しい空のオブジェクトを作り、<code>this</code> にその新しいオブジェクトをセットして、後に続く関数を呼びます。<code>this</code> に指定された関数は値を返しているのではなく、単に <code>this</code> オブジェクトを変更していることに注意してください。<code>this</code> オブジェクトを呼び出し元に返しているのは <code>new</code> です。<code>new</code> によって呼ばれるよう設計された関数はコンストラクター関数と呼ばれます。<code>new</code> によって呼ばれるということがわかるよう、先頭を大文字にすることがよく行われています。</p> +<p>もう 1 つのキーワード <code><a href="/ja/docs/Web/JavaScript/Reference/Operators/new">new</a></code> が出てきました。 <code>new</code> は <code>this</code> と強い関連があります。これは新しい空のオブジェクトを作り、 <code>this</code> にその新しいオブジェクトを設定して、後に続く関数を呼びます。<code>this</code> に指定された関数は値を返しているのではなく、単に <code>this</code> オブジェクトを変更していることに注意してください。 <code>this</code> オブジェクトを呼び出し元に返しているのは <code>new</code> です。<code>new</code> によって呼ばれるよう設計された関数は、コンストラクター関数と呼ばれます。一般的には、これらの関数の先頭を大文字にして、 <code>new</code> で呼び出すように注意します。</p> <p>改良した関数でも、<code>fullName()</code> を単独で呼び出すときの落とし穴がまだあります。</p> -<p>person オブジェクトはだいぶ良くなりましたが、まだ改善の余地があります。person オブジェクトを作るたびに、その中に 2 つの新しい関数オブジェクトを作っています。関数のコードは共有されたほうがいいですよね?</p> +<p>person オブジェクトはだいぶ良くなりましたが、まだ改善の余地があります。person オブジェクトを作るたびに、その中に 2 つの新しい関数オブジェクトを作っています。関数のコードは共有されたほうがいいですよね。</p> -<pre class="brush: js notranslate">function personFullName() { +<pre class="brush: js">function personFullName() { return this.first + ' ' + this.last; } function personFullNameReversed() { @@ -813,9 +845,9 @@ function Person(first, last) { } </pre> -<p>このほうが良いですね。メソッド関数を一度だけ作って、コンストラクターの中でそれへの参照を代入しています。もっとよくなりませんかね? 答えは yes です:</p> +<p>このほうが良いですね。メソッド関数を一度だけ作って、コンストラクターの中でそれへの参照を代入しています。もっとよくならないでしょうか。答えは yes です。</p> -<pre class="brush: js notranslate">function Person(first, last) { +<pre class="brush: js">function Person(first, last) { this.first = first; this.last = last; } @@ -827,24 +859,25 @@ Person.prototype.fullNameReversed = function() { }; </pre> -<p><code>Person.prototype</code> は <code>Person</code> のすべてのインスタンスで共有されるオブジェクトです。これは (「プロトタイプチェーン」という特別な名前を持った) ルックアップチェーンの一部を構成します。<code>Person</code> の何もセットされていないプロパティにアクセスしようとするときはいつでも、JavaScript は <code>Person.prototype</code> が代わりのプロパティを持っているか確認します。結果として、<code>Person.prototype</code> に割り当てられたプロパティはすべて <code>this</code> オブジェクトを通じてコンストラクターのすべてのインスタンスで利用できるようになります。</p> +<p><code>Person.prototype</code> は <code>Person</code> のすべてのインスタンスで共有されるオブジェクトです。これは (「プロトタイプチェーン」という特別な名前を持った) ルックアップチェーンの一部を構成します。<code>Person</code> の何もセットされていないプロパティにアクセスしようとするときはいつでも、 JavaScript は <code>Person.prototype</code> が代わりのプロパティを持っているか確認します。結果として、<code>Person.prototype</code> に割り当てられたプロパティはすべて <code>this</code> オブジェクトを通じてコンストラクターのすべてのインスタンスで利用できるようになります。</p> -<p>これはとても強力です。JavaScript では、プログラム上でいつでもどれかのプロトタイプを変更することができます。ということは、実行時に既存のオブジェクトに対して追加のメソッドを加えることができるのです:</p> +<p>これはとても強力です。 JavaScript では、プログラム上でいつでもどれかのプロトタイプを変更することができます。ということは、実行時に既存のオブジェクトに対して追加のメソッドを加えることができるのです。</p> -<pre class="brush: js line-numbers language-js notranslate"><code class="language-js">s <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Person</span><span class="punctuation token">(</span><span class="string token">'Simon'</span><span class="punctuation token">,</span> <span class="string token">'Willison'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> -s<span class="punctuation token">.</span><span class="function token">firstNameCaps</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// TypeError on line 1: s.firstNameCaps is not a function</span> +<pre class="brush: js">var s = new Person('Simon', 'Willison'); +s.firstNameCaps(); // TypeError on line 1: s.firstNameCaps is not a function -Person<span class="punctuation token">.</span>prototype<span class="punctuation token">.</span>firstNameCaps <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> - <span class="keyword token">return</span> <span class="keyword token">this</span><span class="punctuation token">.</span>first<span class="punctuation token">.</span><span class="function token">toUpperCase</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> -<span class="punctuation token">}</span><span class="punctuation token">;</span> -s<span class="punctuation token">.</span><span class="function token">firstNameCaps</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// "SIMON"</span></code></pre> +Person.prototype.firstNameCaps = function() { + return this.first.toUpperCase(); +}; +s.firstNameCaps(); // "SIMON" +</pre> -<p>興味深いことに、JavaScript の組み込みオブジェクトのプロトタイプにも差し込むことができます。<code>String</code> オブジェクトに文字列を逆さにして返すメソッドを加えてみましょう:</p> +<p>興味深いことに、JavaScript の組み込みオブジェクトのプロトタイプにも差し込むことができます。<code>String</code> オブジェクトに文字列を逆さにして返すメソッドを加えてみましょう。</p> -<pre class="brush: js notranslate">var s = 'Simon'; +<pre class="brush: js">var s = 'Simon'; s.reversed(); // TypeError on line 1: s.reversed is not a function -String.prototype.reversed = function reversed() { +String.prototype.reversed = function() { var r = ''; for (var i = this.length - 1; i >= 0; i--) { r += this[i]; @@ -857,13 +890,13 @@ s.reversed(); // nomiS <p>私たちの新しいメソッドは文字列リテラル上でさえも動きます!</p> -<pre class="brush: js notranslate">'This can now be reversed'.reversed(); // desrever eb won nac sihT +<pre class="brush: js">'This can now be reversed'.reversed(); // desrever eb won nac sihT </pre> -<p>前にも言ったように、プロトタイプはチェーンの一部を構成します。チェーンの根は <code>Object.prototype</code> であり、<code>toString()</code> メソッドを含んでいます。これはオブジェクトを文字列で表そうとするときに呼ばれるメソッドです。これは <code>Person</code> オブジェクトをデバッグするときに役立ちます:</p> +<p>前述の通り、プロトタイプはチェーンの一部を構成します。チェーンの根は <code>Object.prototype</code> であり、 <code>toString()</code> メソッドを含んでいます。これはオブジェクトを文字列で表そうとするときに呼ばれるメソッドです。これは <code>Person</code> オブジェクトをデバッグするときに役立ちます。</p> -<pre class="brush: js notranslate">var s = new Person('Simon', 'Willison'); -s; // [object Object] +<pre class="brush: js">var s = new Person('Simon', 'Willison'); +s.toString(); // [object Object] Person.prototype.toString = function() { return '<Person: ' + this.fullName() + '>'; @@ -872,26 +905,26 @@ Person.prototype.toString = function() { s.toString(); // "<Person: Simon Willison>" </pre> -<p><code>avg.apply()</code> の第 1 引数が null であったことを覚えていますか? もう一度見てみましょう。<code>apply()</code> の第 1 引数は '<code>this</code>' として扱われるオブジェクトです。例えば、これは <code>new</code> のありふれた実装です:</p> +<p><code>avg.apply()</code> の第 1 引数が null であったことを覚えていますか? もう一度見てみましょう。<code>apply()</code> の第 1 引数は '<code>this</code>' として扱われるオブジェクトです。例えば、これは <code>new</code> のありふれた実装です。</p> -<pre class="brush: js notranslate">function trivialNew(constructor, ...args) { +<pre class="brush: js">function trivialNew(constructor, ...args) { var o = {}; // オブジェクトを作成 constructor.apply(o, args); return o; } </pre> -<p>プロトタイプチェーンを設定しないので (これを説明するのは困難です)、<code>trivialNew()</code> は <code>new</code> の完全な複製ではありません。よく使うことはないでしょうが、知っていると役に立ちます。このスニペットで、<code>...args</code> (省略符号を含む) は "<a href="/ja/docs/Web/JavaScript/Reference/Functions/rest_parameters">残余引数 (rest arguments)</a>" と呼ばれます。名前が示唆するとおり、これは残りの引数が含まれます。</p> +<p>プロトタイプチェーンを設定しないので (これを説明するのは困難です)、<code>trivialNew()</code> は <code>new</code> の完全な複製ではありません。よく使うことはないでしょうが、知っていると役に立ちます。このスニペットで、<code>...args</code> (省略符号を含む) は「<a href="/ja/docs/Web/JavaScript/Reference/Functions/rest_parameters">残余引数 (rest arguments)</a>」と呼ばれます。名前が示唆するとおり、これは残りの引数が含まれます。</p> <p>以下の 2 つの呼び出しはほぼ等価です。</p> -<pre class="brush: js notranslate">var bill = trivialNew(Person, 'William', 'Orange');</pre> +<pre class="brush: js">var bill = trivialNew(Person, 'William', 'Orange');</pre> -<pre class="brush: js notranslate">var bill = new Person('William', 'Orange');</pre> +<pre class="brush: js">var bill = new Person('William', 'Orange');</pre> -<p><code>apply()</code> には姉妹関数 <a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/call" title="JavaScript/Reference/Global_Objects/Function/call"><code>call</code></a> があります。<code>this</code> を設定できる点は同じですが、引数に配列ではなく展開された値のリストをとります。</p> +<p><code>apply()</code> には <a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/call"><code>call</code></a> という姉妹関数があります。 <code>this</code> を設定できる点は同じですが、引数に配列ではなく展開された値のリストをとります。</p> -<pre class="brush: js notranslate">function lastNameCaps() { +<pre class="brush: js">function lastNameCaps() { return this.last.toUpperCase(); } var s = new Person('Simon', 'Willison'); @@ -901,51 +934,52 @@ s.lastNameCaps = lastNameCaps; s.lastNameCaps(); // WILLISON </pre> -<h3 id="Inner_functions" name="Inner_functions">内部関数</h3> +<h3 id="Inner_functions">内部関数</h3> -<p>JavaScript での関数宣言は他の関数内でも行えます。これは初期の <code>makePerson()</code> 関数で見ています。大事なことは内部関数内で親関数スコープの変数にアクセスできることです:</p> +<p>JavaScript での関数宣言は他の関数内でも行うことができます。これは最初のころの <code>makePerson()</code> 関数で見ています。 JavaScript で関数を入れ子にすることの重要なことは、内部関数内で親関数スコープの変数にアクセスできることです。</p> -<pre class="brush: js line-numbers language-js notranslate"><code class="language-js"><span class="keyword token">function</span> <span class="function token">parentFunc</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> - <span class="keyword token">var</span> a <span class="operator token">=</span> <span class="number token">1</span><span class="punctuation token">;</span> +<pre class="brush: js">function parentFunc() { + var a = 1; - <span class="keyword token">function</span> <span class="function token">nestedFunc</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> - <span class="keyword token">var</span> b <span class="operator token">=</span> <span class="number token">4</span><span class="punctuation token">;</span> <span class="comment token">// parentFunc はこれを使用できません</span> - <span class="keyword token">return</span> a <span class="operator token">+</span> b<span class="punctuation token">;</span> - <span class="punctuation token">}</span> - <span class="keyword token">return</span> <span class="function token">nestedFunc</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// 5</span> -<span class="punctuation token">}</span></code></pre> + function nestedFunc() { + var b = 4; // parentFunc はこれを使用できない + return a + b; + } + return nestedFunc(); // 5 +} +</pre> <p>内部関数は保守しやすいコードを書くときに多大な利便性をもたらします。ある関数が他の部分のコードでは役立たない関数を 1 つか 2 つ使っているなら、これらのユーティリティ関数を他から呼び出される関数の入れ子にすることができます。内部関数はグローバルスコープでなくなるので、いいことです。</p> -<p>内部関数はグローバル変数を使うという誘惑に対する対抗措置です。複雑なコードを書くとき、複数の関数間で値を共有するためにグローバル変数を使いたくなります。しかし、これでは保守がしづらくなります。内部関数は親関数の変数を共有できるので、グローバルな名前空間を汚染せずに複数の関数をまとめる (いわば 'ローカルなグローバル') ことができます。この仕組みは注意して使用する必要がありますが、便利です。</p> +<p>内部関数はグローバル変数を使うという誘惑に対する対抗措置です。複雑なコードを書くとき、複数の関数間で値を共有するためにグローバル変数を使いたくなります。しかし、これでは保守がしづらくなります。内部関数は親関数の変数を共有できるので、グローバルな名前空間を汚染せずに (いわば「ローカルなグローバル」) 複数の関数をまとめることができます。この仕組みは注意して使用する必要がありますが、便利です。</p> -<h2 id="Closures" name="Closures">クロージャ</h2> +<h2 id="Closures"">クロージャ</h2> -<p>ここでは JavaScript が持つもっとも強力な、しかしもっともわかりにくいとも思われる概念のひとつを紹介します。これは何をしているのでしょうか?</p> +<p>ここでは JavaScript が持つもっとも強力な、しかしもっともわかりにくいとも思われる概念のひとつを紹介します。これは何をしているのでしょうか。</p> -<pre class="brush: js notranslate">function makeAdder(a) { +<pre class="brush: js">function makeAdder(a) { return function(b) { return a + b; }; } -var x = makeAdder(5); -var y = makeAdder(20); -x(6); // ? -y(7); // ? +var add5 = makeAdder(5); +var add20 = makeAdder(20); +add5(6); // ? +add20(7); // ? </pre> -<p><code>makeAdder()</code> 関数がクロージャの正体を明らかにします。この関数はそれぞれ、1 つの引数とともに呼び出されたときに、その値と自身が生成されたときの引数の値とを加算する、新たな '加算' 関数を生成しています。</p> +<p><code>makeAdder()</code> 関数がクロージャの正体を明らかにします。この関数はそれぞれ、1 つの引数とともに呼び出されたときに、その値と自身が生成されたときの引数の値とを加算する、新たな「加算」関数を生成しています。</p> -<p>ここで起きていることは、前出の内部関数で起きていることとほとんど同じです。つまり、ある関数の内部で定義された関数は、外側の関数が持つ変数にアクセスすることができます。唯一の違いは外側の関数が値を返していることであり、それゆえ一般的な考えではローカル変数は存在しなくなると考えられます。しかし、ここではローカル変数が残り続けます。そうでなければ、加算関数は動作しないでしょう。さらに、<code>makeAdder()</code> のローカル変数には異なる 2 つの "複製" が存在します。一方の <code>a</code> は 5、もう一方の <code>a</code> は 20 です。よって、これらの関数を呼び出した結果は以下のようになります:</p> +<p>ここで起きていることは、前出の内部関数で起きていることとほとんど同じです。つまり、ある関数の内部で定義された関数は、外側の関数が持つ変数にアクセスすることができます。唯一の違いは外側の関数が値を返していることであり、それゆえ一般的な考えではローカル変数は存在しなくなると考えられます。しかし、ここではローカル変数が残り続けます。そうでなければ、加算関数は動作しないでしょう。さらに、 <code>makeAdder()</code> のローカル変数には異なる 2 つの「複製」が存在します。一方の <code>a</code> は 5、もう一方の <code>a</code> は 20 です。よって、これらの関数を呼び出した結果は以下のようになります。</p> -<pre class="brush: js notranslate">x(6); // 11 を返す -y(7); // 27 を返す +<pre class="brush: js">add5(6); // 11 を返す +add20(7); // 27 を返す </pre> -<p>これは実際に起きていることです。JavaScript で関数を実行するときは必ず、その関数内で作成されたローカル変数を保持する 'scope' オブジェクトが作成されます。それは関数の引数として渡された変数とともに初期化されます。これはすべてのグローバル変数やグローバル関数が存在している global オブジェクトに似ていますが、2 つの重要な違いがあります。ひとつは、関数を実行し始めるたびに新たな scope オブジェクトが生成されること、もうひとつは、global オブジェクト (<code>this</code> としてアクセスでき、またブラウザーでは <code>window</code> として存在する) とは異なり、これらの scope オブジェクトに JavaScript のコードから直接アクセスできないことです。例えば、現存する scope オブジェクトのプロパティをたどる仕組みはありません。</p> +<p>これは実際に起きていることです。 JavaScript で関数を実行するときは必ず、その関数内で作成されたローカル変数を保持する 'scope' オブジェクトが作成されます。それは関数の引数として渡された変数とともに初期化されます。これはすべてのグローバル変数やグローバル関数が存在している global オブジェクトに似ていますが、2 つの重要な違いがあります。ひとつは、関数を実行し始めるたびに新たな scope オブジェクトが生成されること、もうひとつは、global オブジェクト (<code>this</code> としてアクセスでき、またブラウザーでは <code>window</code> として存在する) とは異なり、これらの scope オブジェクトに JavaScript のコードから直接アクセスできないことです。例えば、現存する scope オブジェクトのプロパティをたどる仕組みはありません。</p> <p>よって <code>makeAdder()</code> が呼び出されたときは、1 個のプロパティを持つ scope オブジェクトが生成されます。そのプロパティとは、<code>makeAdder()</code> 関数に渡される引数の <code>a</code> です。そして <code>makeAdder()</code> は、新たに生成された関数を返します。通常 JavaScript のガベージコレクターは、この時点で <code>makeAdder()</code> のために生成された scope オブジェクトを破棄しますが、返された関数は scope オブジェクトへの参照を維持しています。その結果、scope オブジェクトは <code>makeAdder()</code> が返した関数オブジェクトへの参照がなくなるまでの間、ガベージコレクションの対象になりません。</p> <p>JavaScript のオブジェクトシステムが利用するプロトタイプチェーンと同様に、scope オブジェクトはスコープチェーンと呼ばれるチェーンを構成します。</p> -<p><strong>クロージャ</strong>は、関数と関数が生成した scope オブジェクトを組み合わせたものです。クロージャは状態を保存します。従って、オブジェクトの代わりとしてよく使用されます。<a href="http://stackoverflow.com/questions/111102/how-do-javascript-closures-work">クロージャのすばらしい解説</a> を読むことができます。</p> +<p><strong>クロージャ</strong>は、関数と関数が生成した scope オブジェクトを組み合わせたものです。クロージャは状態を保存します。従って、オブジェクトの代わりとしてよく使用されます。<a href="https://stackoverflow.com/questions/111102/how-do-javascript-closures-work">クロージャのすばらしい解説</a>を読むことができます。</p> |