JavaScript

JavaScript

JavaScriptを
学ぶチュートリアル

著者について

マイケル・ハートル(Michael Hartl)は、ウェブ開発の主要な入門書の一つである「Ruby on Railsチュートリアル」の作成者です。また、「Learn Enough」の共同創立者であり、主執筆者でもあります。以前は、カリフォルニア工科大学(Caltech)で物理学の講師をしており、そこで生涯功労賞(Lifetime Achievement Award for Excellence in Teaching)を受賞しています。ハーバード大学を卒業後、カリフォルニア工科大学で物理学博士号を取得。Y Combinator起業家プログラムの卒業生でもあります。

Learn Enoughの共同創設者Lee Donahoeは、起業家とデザイナーの顔も持つフロントエンド開発者です。「Learn Enough」「Softcover」「Ruby on Rails Tutorial(英語サイト)」のデザインを手掛けたほかに、「Coveralls」の共同創設者兼フロントエンド開発者でもあり、米国ABCテレビの人気番組Shark Tankでも紹介された紳士服企業「Buck Mason」のリードテストカバレッジアナリスト兼テック共同創設者でもあります。USC(南カリフォルニア大学)卒(専攻:経済学、研究:インタラクティブマルチメディア技術)。

著作権とライセンス

Railsチュートリアル Copyright © 2020 by Michael Hartl(最終更新日: 2023/05/09 04:35:53 PT)

Railsチュートリアルで掲載しているすべてのソースコードは、MIT ライセンスおよびBeerware ライセンスの元で提供されています。なお、これらのライセンスはいずれか一方が有効になります。つまり、MITライセンスに基づいて使用する場合は、ビールも購入する必要はありません。

なお、「すべてのソースコード」とは、Railsチュートリアル内で題材としている「Railsアプリケーションのソースコード」を指します。「Railsチュートリアル」という教材は上記ライセンスで提供されていないのでご注意ください。営利・非営利問わず、事業で使用する場合は協業プランをご利用ください。

The MIT License

Copyright (c) 2016 Michael Hartl

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
THE BEERWARE LICENSE (Revision 42)

Michael Hartl wrote this code. As long as you retain this
notice you can do whatever you want with this stuff.
If we meet some day, and you think this stuff is worth it,
you can buy me a beer in return.

第1章Hello, world!

Webブラウザ上で動作する唯一の言語であるJavaScriptは、あらゆるプログラマーにとって欠かすことのできないツールキットです。『JavaScript編』は、ソフトウェア開発者が日常的に使いこなしているツールを中心に、最新のテクノロジー(Node.jsやES6など)を用いて、実用的でモダンなJavaScriptプログラムをできるだけ短期間で書き始められるよう構成されています。

本チュートリアル独自の特長は、JavaScriptをWebに限定せず、最初から汎用プログラミング言語として学ぶようにできている点です。実際、本チュートリアルのコード例はブラウザでの実行に縛られないようになっています。このようにして JavaScriptを「ストーリー仕立てで学べる」実用的な JavaScript入門書が完成しました。本チュートリアルは、Codeacademyのようなブラウザ上のオンラインチュートリアルや、MDN(Mozilla Developer Networkの公式JavaScriptチュートリアル)と合わせて学ぶのにも最適です。

JavaScriptについて隅から隅までもれなく学ぶ必要はありません(そんなことをしたら数千ページを死ぬ気で学び倒さなければならなくなるでしょう)(図 1.11)。そうではなく、本チュートリアルではプロ開発者としての基礎を固めるのに必要な JavaScriptを学びます。

images/figures/flavian_amphitheater
図 1.1: ローマは一日にして成らず、JavaScriptも同じです

JavaScript編』はプログラミング経験が初めての方でも問題ありません。もちろんプログラミング経験があっても大丈夫です。重要なのはプログラミング経験の有無ではなく、皆さんがこれまで以下のチュートリアルシリーズを貫くテーマである「技術の成熟精神(コラム 1.1)」を身に付け始めているかどうかです。以下のチュートリアルシリーズを学び終えた方は、本編を学ぶための準備ができています。

  1. コマンドライン編
  2. テキストエディタ編
  3. Git/GitHub編
  4. HTML編
  5. CSS & Design編
コラム 1.1. 技術の成熟

コンピュータを使いこなすうえで重要なのは、問題の原因を「自力で」見つけ出し、「自力で」解決できる能力です。本チュートリアルシリーズではこれを「技術の成熟精神」と呼んでおり、シリーズ全体を貫く重要なテーマに据えています。

技術の成熟精神」を身に付けるには、『コマンドライン編』『 Git/GitHub編』『HTML編』『CSS & Design編』で基礎をみっちり学ぶことはもちろんですが、何か問題や事例に遭遇したときに「基礎に立ち返って公式ドキュメントや教科書を読み返すべきか」それとも「ネットで解決方法をググるべきか」を見きわめられるようになることが肝心です。困ったときに何も考えずにググってしまううちは、技術の成熟精神を身に付けたとは言えません。

JavaScript編』では、こうしたスキルを身に付ける機会を豊富に用意しています。特に、既に述べたようにネット上にはJavaScriptの参考資料やブログ記事が溢れかえっていますが、基礎を固めると同時にこうした見きわめができていなければ、ネット上の資料やブログ記事を使いこなすのは難しいでしょう。ブログ記事は古いかもしれませんし、情報に誤りがあるかもしれません。公式ドキュメントでも情報の一部が更新されないままになっている可能性も考えられます。特に、日本語ドキュメントは英語版より古いことが多いので注意が必要です。

本チュートリアルの目標のひとつは、ネット上のおびたたしい情報の中から適切なものを見つけ出すスキルを身に付ける、つまり皆さんがドキュメントという宝箱を開けるための「鍵」となることです。著者はもっぱらMozilla Developer Network(MDN)のドキュメントを愛用していますが、これも含めて多くの有用な参考資料を本チュートリアルでその都度紹介いたします。なお、Stackoverflow(英語版)というQ&Aサイトもおすすめです2

特に、技術的に高度な内容に触れる際には、その情報を適切にググれるキーワードとURLも可能な限り添えるようにしています。たとえば JavaScriptで特定のCSSクラスにマッチする要素をページ上のすべての要素に返す方法を知りたい場合は、javascript css class return all elementsで探せます。

重要な情報は英語で書かれていることが多いので、英語力と、英語の技術ドキュメントやエラーメッセージを怖がらずに読む心意気も重要です。幸い、技術英語は比較的やさしい部類に入ります。ドキュメントの著者が英語ネイティブでない場合は多少英文が怪しいこともありますが、むしろ英語ネイティブでない人の書くドキュメントは難しい言い回しが少ない分読みやすいでしょう。

本チュートリアルで、JavaScript開発のプロに欠かせないスキルを身に付けるまでの道のりを紹介します。

1では、新しくプログラミング言語に初めて触るときの定番中の定番である「hello, world」プログラムを書いて、そこにさまざまなテクニックを盛り込んでいくことにします。同時に「Node.js」と呼ばれる、広く使われている高速なJavaScriptプログラム実行環境も紹介します。そして、本チュートリアルの理念「実際に手を動かす」に則って、早々にごくシンプルなJavaScriptアプリケーションを実際のWebにデプロイします。

「Hello, world」をマスターしたら、次はJavaScriptの「オブジェクト(object)」という概念についてある程度学びます。2で文字列オブジェクトについて、3では配列オブジェクトについて、続く4では、その他のオブジェクトについて扱います。これらの章は、JavaScriptによる「オブジェクト指向プログラミング(object-oriented programming)」のやさしい入門書となっています。

5では「関数(function)」の基礎を学びます。関数は、プログラミング言語で必ずと言ってよいほど使われている概念です。さらに6では、「関数型プログラミング(functional programming)」と呼ばれるエレガントで強力なコーディングスタイルを学びます。

JavaScriptに組み込まれているオブジェクトの基本をひととおり学んだ後は、7で独自のオブジェクトを作る方法を学びます。具体的には、英語のフレーズ(phrase: 句、単語より大きく文より小さい単位)を定義するオブジェクトを定義して、そのフレーズが「回文(palindrome: 前から読んでも後ろから読んでも同じになる)」かどうかを調べるメソッドを作ります。

最初に実装する回文チェックメソッドはかなり初歩的なものですが、8では「TDD(test-driven development: テスト駆動開発)」と呼ばれる強力な手法を用いてメソッドを拡張します。ソフトウェア開発における一般的な「テスト」についてさらに詳しく学ぶと同時に、NPMモジュール(NPMはNode Package Managerの略)と呼ばれる完結したソフトウェアパッケージの作り方も学びます。このときに、JavaScriptのソフトウェアパッケージをNPMで管理する巨大なエコシステムに皆さんも参加することになります。

9では、作成したNPMモジュールをJavaScriptWebアプリケーションに適用し、回文を検出するWebサイトを作ります。このときイベント(event)の概念とDOM操作(DOMはDocument Object Modelの略)についても学びます。最初はごくシンプルな実装からスタートし、アラート(alert)、プロンプト(prompt)、HTMLフォーム(form)などの洗練された拡張機能を徐々に追加していきます。

10では、ある程度大きなシェルスクリプトをJavaScriptで書く方法を学びます。このような用途を学ぶことで、汎用プログラミング言語としてのJavaScriptの重要性が浮き彫りとなります。ファイルの読み込みやURLからの読み込みなどの例をこなし、最後に、ダウンロードしたファイルをHTML Webページのように操作する方法を紹介します。

11では、これまで学んだことを応用して、商用レベルのWebサイトを実際に構築します。特に、『CSS & Design編』で作ったサンプルアプリケーションを拡張することで、ユーザーのクリックに反応して画像やCSSクラスやページテキストをJavaScriptで動的に変化させる機能を追加します。Gitを使ってリポジトリを直接構築するので、『CSS & Design編』を終えていない方も問題なく学習できるようになっています。

本チュートリアルでは、動的レンダリングを行えるフロントエンドとデータベースのバックエンドを備えた本格的なウェブ開発までは扱いませんが、本チュートリアルを終える頃には、そのためのスキルを会得する基礎を十分身に付けられるでしょう。

ここで学ぶJavaScriptの基礎知識は、SinatraRubyを学ぶときはもちろん、特にRuby on Railsでフルスタックウェブ開発を学ぶうえで非常に有用です。

1.1 JavaScriptについて

JavaScriptを最初に開発したのは、コンピュータ科学者のBrendan Eichです(図 1.23)。最初のJavaScriptが初期の商用WebブラウザであるNetscape Navigatorに搭載されましたが、このときは「LiveScript」という名前でした(コラム 1.2)。この頃のJavaScriptの使いみちは、もっぱら『CSS & Design編』でも紹介したDOM(Document Object Model)操作が中心でしたが、現在ではその他にバックエンドでの利用や、汎用プログラミング言語としての利用も増えています。

brendan_eich
図 1.2: JavaScriptの生みの親Brendan Eich
コラム 1.2. 「名前が何だというのですか?」

名前が何だというのですか?バラをどんな名前で呼ぼうと、甘い香りを放つことに変わりはないではありませんか。

—ウィリアム・シェークスピア『ロミオとジュリエット』(第二幕、場面二)より

現在私たちがJavaScriptと呼んでいる言語は、Netscape社では当初「LiveScript」と呼ばれていましたが、リリースが迫っていた当時は、今は無きサン・マイクロシステムズ社の開発したJava言語が大人気を博していました。Netscape社は、このJava人気にあやかろうとしてLiveScriptの名前を「JavaScript」に変更しました。そのため、当時の開発者たちは「JavaScriptとJavaは何か関係があるのか?」と果てしなく混乱したのです。(答え: 両者は何ひとつ関係ありません)

その後、ブラウザ間の互換性を高めるために、ECMAScript(「エクマスクリプト」と発音します)と呼ばれるJavaScriptの標準化版が誕生しました。当時は、ブラウザごとにJavaScriptの挙動が細かく異なっていて深刻な問題になっていたのです。

厳密なことを言えばですが、一般にJavaScriptと呼ばれている言語は本来ECMAScriptと呼ぶのが適切です。JavaScriptはあくまでECMAScriptの最も一般的な実装にすぎませんが、この言語が一般にJavaScriptと呼ばれているので、本チュートリアルでもこの慣習に従っています。

なお例外として、ECMAScriptのバージョン6を指すES6という短縮名を使うこともあります。なお、ES6では大規模な変更が行われてECMAScript JavaScript標準に便利な機能が多数追加されています。あまりにも便利になったので、「ES6はES5以前とは別の言語だ」と言う人もいるほどです。

なお、ES6の正式な仕様名は「ECMAScript 2015」です(ES5以前は仕様に年号を含んでいません)。バージョン番号と年号の微妙なずれがあまりにも紛らわしいので、ES6より新しい仕様を指すときは、もっぱらバージョン番号よりも年号を用いて「ECMAScript 2020」のように表記する方が一般的です。

最後に、JavaScriptのスペルのSをうっかり小文字にして「Javascript」としてしまうスペルミスが実に多いことは知っておいて損はないでしょう。公式に近いドキュメントでもそうしたミスがあるくらいなので、明らかなスペルミスというよりは事実上「やむを得ず黙認」されているのが現状です。個人的には、JavaScriptよりも「Javascript」の方が鼻につかなくて好ましいとこっそり思っていますが、スペルミスには違いないので、本チュートリアルでは技術的に正しい「JavaScript」で統一しています。

本チュートリアルでは、JavaScriptのプログラミングを広く理解していただくために、主に以下の4つの方面からJavaScriptを攻略します。

  1. フロントエンド JavaScriptプログラム(ユーザーのブラウザ上で動作する)
  2. Node.jsのREPL(Read-Evaluate-Print Loop)によるコマンドプロンプトでの対話操作
  3. スタンドアロン4のJavaScriptファイル(NPMなど)
  4. シェルスクリプト(『テキストエディタ編』)

JavaScriptの最初の学習は、C言語誕生した頃からプログラミングの定番のお題となっている「Hello, world」を4種類作ることから始めることにします。hello, worldプログラムの作成作業には、システムが正しく設定されているかどうかの確認も含まれます。つまりhello, world!という文字列を画面に表示する簡単なプログラムを実行できれば、システムが正しく設定されているというわけです。hello, worldプログラムはごくシンプルに設計されていますが、プログラムを実行するという課題に集中できるようにするためでもあります。

JavaScriptの本来の用途は「Web上で実行されるプログラムを書くこと」であり、現在も最も一般的な用途でありつづけています。そこで、手始めにWebブラウザに挨拶文を表示するプログラムを書いてWebサイトにデプロイします。

続いて、Node.jsというJavaScript実行システムを用いて、同じJavaScriptプログラムを3通りの方法で書きます。1つ目はNode.jsのREPL上で動かし、2つ目はhello.jsという名前のJavaScriptライブラリファイル内に書き、3つ目はhelloという名前の実行可能シェルスクリプトの中に書きます。

Node.jsについては後ほど詳しく説明しますが、これを使うとWebブラウザがなくてもJavaScriptをコマンドプロンプトで動かせるようになります。Node.jsの中には、Chromeブラウザで使われているV8と呼ばれる驚くほど高速で強力なJavaScriptエンジンが含まれています。

以降の説明は「macOS」「Linux」「AWS Cloud9 IDE」などのUnix互換システムにアクセスできることを前提としています。そうした環境がない場合は、「Learn Enough Dev Environment to Be Dangerous(英語)」や「Rails Girlsインストールレシピ」を参考に環境を構築することをおすすめします。Cloud9 IDEで開発環境を作成する場合は、他のチュートリアルと区別するためにもjavascript-tutorialという名前を開発環境に付けておくとよいでしょう。

クラウドIDEはデフォルトでBashシェルプログラムを使用しますが、Macユーザーは好きなシェルプログラムを使用することができます。詳細については「Using Z Shell on Macs with the Learn Enough Tutorials(英語)」もご参照ください。

1.2 Webブラウザ内で動くJavaScript

JavaScriptは汎用プログラミング言語として使われるようになってきましたが、もちろん本来のすみかであるWebブラウザでも活躍しています。そこで、最初の「hello, world」プログラムでは、JavaScriptで作成した通知をWebページに表示することにしましょう。

まず、mkdir -pコマンドを実行してこのチュートリアル用のディレクトリを作成します5。今後は必要に応じてこの中にもディレクトリを作成していきます。作成したディレクトリに移動したらtouchコマンドでHTMLインデックスファイルを作成します6

$ mkdir -p ~/repos/js_tutorial
$ cd ~/repos/js_tutorial
$ touch index.html

次に、『Git/GitHub編』で学んだ方法を応用して、このプロジェクトをGitのバージョン管理下におきます。

$ git init
$ git add -A
$ git commit -m "Initialize repository"

この時点で、最初の編集を行う準備が整いました。まずはJavaScriptは使わないシンプルな HTML スケルトンをindexページに追加してみましょう(リスト 1.1)。これをWebブラウザで表示した結果を図 1.3に示します。

リスト 1.1: HTMLスケルトン index.html
<!DOCTYPE html>
<html>
  <head>
    <title>JavaScriptを学ぼう</title>
    <meta charset="utf-8">
  </head>
  <body>
    <h1>Hello, world!</h1>
    <p>このページにはJavaScriptで書かれたアラートがあります。</p>
  </body>
</html>
images/figures/html_skeleton
図 1.3: 最初の静的なindexページ

まだJavaScriptを足していないので、このままだとページの文面がうそになってしまいますね。そこで、コマンドを1つ含む以下のscriptタグをHTMLに追加することにします。追加する場所についてはこの後説明します。

<script>
  alert("hello, world!");
</script>

上のコードで使っているalert()は、JavaScriptの「関数(function)」を呼び出しています。JavaScript関数呼び出しの構文を図 1.4に示します。

images/figures/function_anatomy
図 1.4: JavaScriptの関数呼び出しの構文

関数呼び出しは「関数名」「かっこ()」を続けて書きます。

関数を関数名()のように書くとその関数が呼び出され、何らかの機能が実行されます。これを「関数呼び出し」といいます。関数を呼び出すには、関数名()のように丸かっこ()も付けなければなりません。

関数の種類によっては、関数呼び出しの()の中に「引数(ひきすう: argument)」を書けるものもあります。引数は0個(つまり()の中が空)のこともあれば、1個のこともありますし、2個以上書けることもあります。

関数にどんな引数をいくつ渡せるかは、関数ごとに決まっています。自分で関数を作るときは、どんな引数をいくつ渡せるかを自分で決めなければなりません。

図 1.4では関数呼び出しの末尾にセミコロン;が置かれていますが、これは「そのコード行がここで終わる」ことを表します。ご注意いただきたいのは、「関数呼び出しだからセミコロンを付ける」のではないということです。関数呼び出し以外の場合であってもコードの行末には原則としてセミコロンをおきます。関数を自分で定義する方法などについては5で詳しく説明します。

alert()関数の場合は、引数に「文字列(string)」を書けます7。ここに書いた文字列は、ブラウザ上のアラートボックスに表示されます。

それでは、いよいよindexページにalert()関数を追加して実際に動かしてみましょう(リスト 1.2)。

なお、このscriptタグはページのどこに置いても「一応」動きますが、HTMLのheadタグの中に置くのが普通です。特に、この後の5.2のように外部のJavaScriptファイルをインクルードする場合はheadタグの中に置くのが定番です。

リスト 1.2: JavaScriptで「Hello, world!」する index.html
<!DOCTYPE html>
<html>
  <head>
    <title>JavaScriptを学ぼう</title>
    <meta charset="utf-8">
    <script>
      alert("hello, world!");
    </script>
  </head>
  <body>
    <h1>Hello, world!</h1>
    <p>このページにはJavaScriptで書かれたアラートがあります。</p>
  </body>
</html>

ブラウザ表示を更新すると、ブラウザ上部に「hello, world!」と書かれたアラートボックスが表示されます(図 1.5)。なお図はSafariブラウザの場合です。ChromeやFirefoxだとアラートボックスの細かなデザインや文言が少し異なる可能性があります(コラム 1.3)。

images/figures/js_hello_world
図 1.5: 「hello, world!」アラートボックスが表示された様子
コラム 1.3. ブラウザごとにメッセージが異なる場合がある

残念ながら、ブラウザで表示されるさまざまなアラートボックスやバリデーションに表示されるブラウザ組み込みのデフォルトメッセージはブラウザごとに微妙に異なることがほとんどです(参考)。これは日本語でも英語でも発生します。ブラウザ組み込みのメッセージをどう書くかはブラウザの仕様に含まれていないので、ブラウザメーカーごとにまちまちなのが実情です。さらにブラウザの英語メッセージがブラウザメーカーによって日本語に翻訳されると、ばらつきがひどくなることもあります。今後ブラウザメーカーが手を組んでメッセージを統一しない限り、この問題は解決しないでしょう。

ブラウザごとのメッセージのばらつきは、通常はさほど問題にならないと思いますが、Webサイトのヘルプを書いたりスクリーンショットを撮影するときに対応が面倒になることがありますので、知っておいて損はないでしょう。

1.2.1 作ったものをデプロイする

仕上げに、今作った素晴らしいJavaScriptアプリ(これでもJavaScriptアプリですよ)をWebサイトにデプロイしましょう。これまで『Git/GitHub編』『HTML編』『CSS & Design編』で行ったのと同じ要領で、GitHub Pagesに無料のWebサイトをホスティングすることにします。

このようにチュートリアルの早い段階でWebサイトへのデプロイを行うことで、ここで学んだ概念が実際に動くことを強力に実証できます。このJavaScriptアプリが素晴らしいという冗談はさておき、実際に動く本チュートリアルのWebサイトをデプロイしていきます。今では数秒でデプロイを完了できますが、ほんの数年前まではそれはそれは面倒な作業でした。

では、以下を実行してリスト 1.2の変更結果をGitにコミットしましょう。

$ git commit -am "Add a JavaScript 'hello, world'"

次に、GitHub上にjs_tutorialという名前で新しいリモートリポジトリを作成します(図 1.6)。ここでは詳しく説明しませんので、手順がわからない場合は『Git/GitHub編』をご覧ください。

images/figures/new_repository
図 1.6: GitHub上に新しいリポジトリを作成する

次に、以下のコマンドを実行してリモートリポジトリを設定し、ブランチをプッシュします。<ユーザー名>にはGitHubのユーザー名を記入してください。

$ git remote add origin https://github.com/<ユーザー名>/js_tutorial.git
$ git push -u origin main

あとはGitHubリポジトリの「Settings」タブ(図 1.7)の左サイドバーにある「Pages」をクリックしてを編集し、図 1.8図 1.9に示すように、GitHub Pagesでmainブランチをするよう設定します。このとき、リポジトリが「public」であることを確認しておいてください。privateだとGitHub Pagesを利用できません。

これでデプロイは完了です。

images/figures/github_settings
図 1.7: GitHubリポジトリの設定を編集する
images/figures/github_pages_main_branch
図 1.8: mainブランチをGitHub Pagesで公開する設定
images/figures/github_pages_save
図 1.9: 新しいGitHub Pagesの設定を保存する

これで、以下のURLをブラウザで開くと今作ったindexページのJavaScriptコードが動き、アラートボックスが表示されます8

https://<ユーザー名>.github.io/js_tutorial

図 1.5のときとまったく同じ「hello, world」が表示されていますが、今度はインターネット上でちゃんと「実際に動いている」点が大きな違いです(図 1.10)。たった1行とはいえ、あなたが書いたJavaScriptコードが誰からでも見える場所で実際に動いているのです!

images/figures/js_hello_world_live
図 1.10: インターネット上で JavaScriptのhello, world!ページが実際に動いている様子

1.2.2 演習問題

  1. 先ほどのアラートボックスに続けて、もうひとつアラートボックスを表示するとどうなるでしょうか?実際に試してみてください。終わったら元に戻しましょう。

1.3 JavaScriptを「REPL」で動かす

お次は、今のhello worldプログラムをREPL(「レプル」と発音します)で動かしてみましょう。REPLは「対話機能」とも呼ばれ、コマンドプロンプト上で「Read(読み取り)」「Eval(評価)」「出力(Print)」を繰り返す(Loop)という意味です。RubyにもirbというREPL機能があるように、今どきのプログラミング言語にはREPL機能があるのが当たり前になっています。もちろんJavaScriptも例外ではありません。お気づきかと思いますが、JavaScriptには2種類のREPLがあります。

1.3.1 ブラウザコンソール

1つ目のREPLは、ブラウザの「コンソール(console)」です。今どきのブラウザは、コンソールなどの開発ツール(devtools)を標準で利用できるのが普通です。Google Chromeブラウザでは最初からdevtoolsが含まれていますが、Safariブラウザの場合は 開発メニューを有効にする必要があります。

本チュートリアルではdevtoolsについて詳しく説明しませんので、自分が使うブラウザでdevtoolsをセットアップする方法については例の「技術の成熟」精神(コラム 1.1)を発揮して自力でやってみてください。

たいていのdevtoolsは、ブラウザ画面を右クリック(またはCtrlキーを押しながらクリック)して、「検証」(Chrome)や「要素を調査」(Firefox)や「要素の詳細を表示」(Safari)あたりをクリックすればWebインスペクタが表示されます(図 1.11)。SafariでWebインスペクタを表示したときの様子を図 1.12に示します。

images/figures/inspect_element
図 1.11: Safariの「要素の詳細を表示(Inspect Element)」メニュー
images/figures/developer_tools
図 1.12: SafariでdevtoolsのWebインスペクタを表示した様子

あとはページの下に表示されたWebインスペクタで「Console」タブ(または同等のタブ)をクリックすれば、コンソールにアクセスできるようになります(図 1.13)。

後ほど 5.2で説明するように、コンソールは実に有用なデバッグツールでもあります。コンソールは、DOM(Document Object Model)やアプリケーション環境を裏舞台から調査して、アプリケーションに影響を与える可能性のある警告やエラーを確認できます。

コンソールにはさまざまな警告やエラーが赤い文字で大量に表示されることもあります。エラーのほとんどは「無視してよい」ものですが、中には「無視してはいけない重要な警告やエラー」もたまにあります。この見分けがつくようになれば、皆さんに「技術の成熟」精神が身についた証拠です。

今の段階ではおそらくコンソールにエラーは表示されないはずですが、皆さんのブラウザ設定によっては何かエラーが表示される可能性もあります。でも今の段階で表示されるエラーは「すべて無視しても大丈夫」なのでご安心ください!今は、たとえエラーが出ても目をそむけない度胸を養うことが重要です。

images/figures/console
図 1.13: JavaScriptを対話的に実行できるコンソール

さて、コンソールのREPLでhello worldプログラムを書く準備がこれで整いました。

コンソールのREPLでメッセージを表示するには、先ほどのalert()関数ではなく、consoleというJavaScriptの「オブジェクト(object)」を使います。

JavaScriptのconsoleオブジェクトは、「コンソールそのもの」と、コンソールに関連する「データ」やさまざまな「関数」などを表現します。consoleオブジェクトにはlog()という関数が備え付けられていて、この関数の引数に何か文字列を渡すと、その文字列を(ブラウザそのものではなく)コンソール上に表示できます。

consoleオブジェクトのlog()関数を呼び出すときは、以下のようにオブジェクト指向言語で広く用いられている「ドット(.)記法」を用います(リスト 1.3)。

リスト 1.3: コンソールでhello, worldを出力する
> console.log("hello, world!");

log()は関数の一種ですが、特に上のように特定のオブジェクトに続けてドット.記法で書いて呼び出す関数は「メソッド(method)」といいます。メソッドは関数の一種であり、呼び出し方に特徴があります。

なお、リスト 1.3console.log("hello, world!");をコンソールに入力するときは、冒頭にあるコマンドプロンプト(>)を含めないでください。

正しくコンソールに入力してReturnキーを押すと、図 1.14のような結果になるはずです(その下に表示されている「undefined」については、2.3で後述しますので今は気にしないでください)。

images/figures/console_hello_world
図 1.14: ブラウザコンソールにhello, worldが出力された様子

ところで勘の鋭い方は、リスト 1.3の末尾には図 1.4のとおりにセミコロン;が置かれているのに、図 1.14の末尾にはセミコロンがないことにお気づきかもしれません。いい点を衝いていますね!

実を言うと、対話型コンソールの場合は末尾のセミコロンはあってもなくても動作は変わりません。それを示すために図 1.14ではわざとセミコロンを入力しなかったのです。実際、ベテランがREPLで何かするときは、いちいち末尾にセミコロンを入力しないのが普通です。「セミコロンを付ける派」と「付けない派」がいることを知っておくと、他の人が書いたJavaScriptコードを読んでも戸惑わずに済むでしょう。

本チュートリアルでは、コンソール入力についても「セミコロンあり」の書式で統一しています。

1.3.2 Nodeのプロンプト

どんなブラウザでも必ずJavaScriptプログラムを実行できるようになっています。しかし、ブラウザとは無関係に、コマンドライン上で実行する汎用プログラミング言語としてJavaScriptを扱うこともあります。そのためには、JavaScriptプログラムを評価して実行する何らかのコマンドライン用プログラムを別途インストールして使うことになります。現代では、コマンドラインでJavaScriptを動かすのに使うプログラムといえば、ほぼNode.js一択です。「ノードジェーエス」と発音しますが、「Node」と略記されることもあります。

コラム 1.4. 参考: Denoについて

2020年頃から、Node.jsの後継としてDenoが急速にクローズアップされつつあります。Denoの作者はNode.jsの作者でもあるRyan Dahlで、Node.jsのさまざまな問題点(npmパッケージの煩雑な管理やセキュリティなど)を抜本的に改善するためにDenoをリリースしました(参考)。Denoは「Node」のスペルを並べ替えた名前になっていて、アイコンが恐竜(Dinosaur)なのもDenoのもじりなのが面白い点です。

Denoは2021年7月の時点ではまだ発展途上の段階にあり、Node.jsは長く使われていて情報も多いので、Node.jsからDenoに急いで乗り換える必要はまだないと思われますが、今後DenoがNode.jsに取って代わる可能性も考えられるので、ときどき動向をチェックしておくとよいでしょう。

Node.jsは皆さんの使っているコンピュータに既にインストールされている可能性もあります。以下のようにwhichコマンド(『コマンドライン編』を参照)を使えばさくっとチェックできます。

$ which node
/usr/local/bin/node

nodeという実行ファイルへのパスが表示されればNode.jsを使える状態になっているので、バージョンも確認してみましょう。

$ node -v
v18.12.1

macOSにNode.jsがインストールされていない場合や、表示されるバージョンが違う場合9は、以下の手順でインストールできます。ここでは、Node.jsのバージョン管理ツールnodebrewを使ってインストールします。Homebrewがインストール済みであることを確認し、以下のコマンドでnodebrewをインストール、セットアップします。

$ brew install nodebrew
$ nodebrew setup

次に、本チュートリアルで使用するNode.jsのバージョンをインストールし、使用するバージョンとして指定します。

$ nodebrew install-binary 18.12.1
$ nodebrew use 18.12.1

インストールしたバージョンと、現在のバージョンは以下のコマンドで確認できます。

$ nodebrew ls
$ node -v

nodebrewを使わずにインストールする場合は、Node.jsサイトに記載されている指示に沿ってインストールします。

インストールが終わっていれば、Node.jsの実行は簡単です。コマンドラインで以下のようにnodeというコマンドを実行するだけです(リスト 1.4)。

リスト 1.4: コマンドラインでNodeプロンプトを起動する
$ node
>

Node.jsを起動すると表示される>は、ブラウザコンソールのときと同様、Nodeのプロンプトを表します。>が表示されているときはNodeのコードを入力可能であることを示します。間違えて>を入力しないようにしましょう。

なお本チュートリアルでは、特記しない限り「コンソール」はブラウザコンソールとNodeコンソールの両方を指すことにします。

さて、Nodeプロンプトでhello worldプログラムを動かすには、Nodeプロンプトに以下を入力します(リスト 1.3)。

> console.log("hello, world!");
hello, world!

なお、Nodeコンソールでもundefinedが表示される可能性がありますが、無視して構いません(詳しくは 2.3で説明します)。

ご覧いただいたように、hello worldを表示するプログラムは、ブラウザコンソールでもNodeプロンプトでも同じなのです。

> console.log("hello, world!");

1.3.3 演習問題

  1. ブラウザコンソールでわざとalert()を実行したらどうなるでしょうか?同じことをNodeコンソールでやった場合はどうなるでしょうか?

1.4 JavaScriptコードをファイルに書く

ブラウザコンソールやNodeコンソールのようなREPL環境でJavaScriptを実行できるのはとても便利です。しかし「本物のプログラミング™」はテキストエディタで開いたファイルの中で行うものです。そこで今度は、これまで2種類のREPL環境で実行したhello worldプログラムをファイルに保存して実行してみましょう。ファイルに保存したJavaScriptプログラムは、この後の5.2からテンプレートとしても使い回す予定です。

helloプログラムを保存するJavaScriptファイルを、以下のコマンドで作成します。拡張子.jsは、JavaScriptファイルを表します。

$ touch hello.js

続いて、このファイルをお使いのテキストエディタで開き、リスト 1.5のコードを入力します。このコードは、コマンドプロンプト>がない点を除けばリスト 1.3のコードとまったく同じであることにご注目ください。

リスト 1.5: hello, worldプログラムをJavaScriptファイルに書く hello.js
console.log("hello, world!");

変更を保存すれば、先ほどNodeプロンプトを起動するのに使ったのと同じnodeコマンド(リスト 1.4)を以下のように実行することで即座にhello worldが表示されます。違いは、nodeコマンドの後ろにファイル名を引数として追加した点だけです。

$ node hello.js
hello, world!

今度も「hello world!」が表示されましたが、ターミナル画面にはNodeプロンプト>抜きで表示されています。なお、内部では先ほどのundefinedが戻り値として返されていますが、対話的な実行ではないのでターミナルには表示されません。

たった1行のシンプルなコード例ですが、これは大きな進歩です。ブラウザコンソールやNodeコンソールは長いJavaScriptプログラムを実行するには不向きですが、ファイルに保存すればいくらでも長いプログラムを書けるからです。

1.4.1 演習問題

  1. console.logに渡す引数をリスト1.6のように2つにするとどうなるでしょうか?ブラウザコンソール、Nodeコンソール、JavaScriptファイルでそれぞれ試してみてください。
リスト 1.6: 引数を2つに増やす hello.js
console.log("hello, world!", "how's it going?");

1.5 JavaScriptをシェルスクリプト内で実行する

1.4で動かしたコードはまったく問題なく動きます。しかし実用を考えると、JavaScriptプログラムをコマンドラインのシェルで動かす場合は、『テキストエディタ編』で学んだ「実行可能スクリプト(executable script)」の形にしておく方が有用なことがよくあります。

JavaScriptがブラウザなしでもコマンドラインで動くようになったおかげで、今やJavaScriptは従来の「Ruby」「Python」「Perl」と並ぶシェルスクリプト記述言語としても十分使えるようになってきました。つまり、拡張子.jsを付けていちいちnodeコマンドで実行しなくても、普通のシェルスクリプトと同じようにいきなりコマンドプロンプトで実行できるということです。

Node.jsを用いて実行可能スクリプトを作成する方法を見てみましょう。手始めに以下を実行して、helloというファイルを作成します10

$ touch hello

今作ったファイルに.jsという拡張子がない点にご注意ください。拡張子を付けなかった理由は「ファイル名だけで使い方がわかる」「どの言語で書かれたのかをユーザーに見せる必要はない」からです。

もうひとつの理由は、使った言語を隠しておけば、今後言語を他のものに変えても使い方が変わらずに済むためです。hello.jsという名前のままだと、今後これをRubyで書き直したらhello.rbという名前にしなければならなくなり、コマンドプロンプトでの使い方も変わってしまって不便です。helloのような単純なプログラムではそこまで気にする必要もありませんが、今後ある程度大きなシェルスクリプトを書くようになってくればありがたみがわかってくると思います。詳しくは10.3で解説します。

さて、実行可能スクリプトに変えるには少々工夫が必要です。具体的には2つのステップがあります。

1つ目は、『テキストエディタ編』で学んだ「shebang」をリスト 1.5のコードの冒頭に追加して、「このスクリプトはnodeで実行しなければならない」という情報をシステムに伝えられるようにします。

shebang行の記述方法はシステムによって変わることがある点に注意が必要です。つまり環境が変わると動かなくなる可能性があるのです。以下のようにwhichコマンドを使えば正しいパスを確認できます11

$ which node
/usr/local/bin/node

上で確認したパスをhelloファイルのshebang行に反映した結果をリスト 1.7に示します。

リスト 1.7: hello, worldのシェルスクリプト版 hello
#!/usr/local/bin/node

console.log("hello, world!");

このファイルを1.4のときと同様にnode helloコマンドで実行することも可能ですが、本物のシェルスクリプトならnodeを書かなくても実行できるべきです(そのためにshebangを書いたのですから)。

このファイルはそのままでは実行できません。そこで、2つ目の手順として以下のようにchmodコマンドで+x(実行権限を追加)オプションを指定します。chmodは「change modeの略」とおぼえましょう。

$ chmod +x hello

これでhelloファイルが実行可能になったはずです。

作ったスクリプトは、まだPATH環境変数12のパスが通っていないので、helloだけでは実行できません。以下のように冒頭に./を追加して./helloと入力することで実行できます。なお、このドット.は「カレントディレクトリ」(現在のディレクトリ)を意味します。PATH環境変数のパスが通っているディレクトリにhelloファイルを移動すれば、helloと入力するだけで任意のディレクトリから実行できるようになります。

$ ./hello
hello, world!

これで、いつでも手を加えて改良できるJavaScriptシェルスクリプトが動くようになりました!先ほど述べたように、実際に役に立つユーティリティスクリプトの例を10.3で紹介します。

本チュートリアルでは以後、主にREPLを用いて初期調査を行い、最終的にはJavaScriptを含んだファイルの形に落とし込みます(JavaScriptのみの場合もHTMLの場合もあります)。

1.5.1 演習問題

  1. 今作ったhelloスクリプトを、自分の環境のPATH環境変数が通っているディレクトリに追加して、./を冒頭に追加しなくてもhello入力するだけでいつでも実行できるようにしてみてください(『テキストエディタ編』によいヒントがあります)。
1. 本画像はパブリックドメインです。
2. 日本語版もありますが、英語版ほど情報は多くありません。
3. 画像引用元: Wikimedia(2018-02-17)、Copyright © 2012 Darcy Padilla、クリエイティブ・コモンズ「表示 - 継承 3.0 非移植 (CC BY-SA 3.0)」 ライセンス条項に基づき無改変にて利用。
4. standalone: 単独で利用できる。
5. Cloud9などのクラウドIDEを使う場合は、本チュートリアルのコマンドでホームディレクトリを表す「~」の部分を「~/environment」に置き換えることをおすすめしますが、どちらでも同じように動作します。
6. こうしたコマンドについては『コマンドライン編』で復習できます。
7. 文字列オブジェクトについて詳しくは2で学びます。
8. URLのドメイン名をカスタムドメインに変えることもできます。詳しくはGitHubのドキュメントや『Learn Enough Custom Domains to Be Dangerous』をご覧ください。
9. 通常では使用するバージョンはNode.jsサイトに記載されている推奨版をオススメしますが、本チュートリアルではv18.12.1で動作確認を行なっており、他のバージョンではうまくいかない可能性があります。
10. 作成したファイルの改行コードが「CRLF」になっていると、シェルスクリプト実行時に「bad interpreter」エラーが発生する可能性があります。WindowsではデフォルトでCRLFが使われ、macOSやLinuxではデフォルトでLFが使われます。エラーが発生した場合は、エディタで改行コードをCRLFからLFに変更することで修正できます。
11. Node.jsのインストール方法によっては、表示されるパスが変わっている場合があります。
12. 詳しくは『テキストエディタ編』で学びました。
前の章
第1章 Hello, world! JavaScript編
次の章