サイトにアクセスしようとしたところ、Javaのアップデートが必要とのメッセージが─あなたにも、きっと身に覚えがあるはず。
サイトのインタラクティブな機能などで、Javaに親しんでいる方は多いと思いますが、JavaScriptとなると、あまり馴染みがないかもしれません。むしろこの2つが同じものだと誤解されがちです。
この記事では、JavaScriptとは何か、そして、JavaとJavaScriptの違いについて説明します。さらに、JavaScriptの重要な機能にも触れます。
それでは参りましょう。
JavaScriptについて、動画版の説明もご用意しています。
JavaScriptとは?
JavaScriptとは、簡単に言えば、ウェブページにインタラクティブな機能や動的コンテンツを追加する、人気のスクリプト言語です。よく知られているJavaScriptコンテンツの例としては、フォーム、フォトギャラリー、画像スライドショー、アニメーションなどがあります。
また、JavaScriptはわりと直感的でわかりやすく、学習しやすいのが特徴です。ウェブサイト制作初心者の方が最初に学ぶのにぴったりです。
JavaScriptは、高度にインタラクティブなサイトの機能を実現する、一番最後のレイヤーです。HTMLは、ページの基本構造を規定します。CSSはスタイルを適用することで、サイトの見た目を司ります。そして、JavaScriptは一種のスパイスです。
JavaScriptを学ぶ際には、HTML、CSS、JavaScriptの関係を理解し、それらがどのように組み合わさりサイトが表示されるのかを知る必要があります。
JavaScriptは何に使うのか
JavaScriptには様々な用途があります。インタラクティブなWebページやモバイルアプリで、一度は体感したことがあるはずです。JavaScriptの最も典型的な用途が、インタラクティブなフォームやアニメーションなどの要素の実装です。もちろん、それ以外にも幅広い活用法があります。
- ウェブブラウザベースのゲーム:2D、3Dゲーム
- モバイルアプリケーション開発:端末の機種を選ばないので便利
- プレゼンテーション:ウェブベースのアニメーションスライドの作成
JavaScriptは、クライアントサイドで機能することがほとんどですが、Webサーバーの作成など、サーバーサイドでも活躍します。
JavaとJavaScriptの違い
まず、注意していただきたい点から。「Java」という言葉が共通しているものの、JavaとJavaScriptは完全なる別物です。JavaもJavaScriptも、WebページやWebアプリケーションを開発するための言語です。しかし、両者には以下のような明確な違いがあります。
- オブジェクト指向プログラミング:Javaはオブジェクト指向のプログラミング言語です。一方で、JavaScriptはオブジェクトベースのスクリプト言語です。
- 構文:JavaScriptの構文は、Javaほど正式ではなく、構造化されていません。そのため、多くの人にとってより分かりやすいものとなっています。
- コンパイル:Javaはコンパイル言語ですが、JavaScriptは実行時に一行ずつ解釈されるインタプリタ言語です。コンパイル言語の方が高速ですが、インタプリタ言語の方が、柔軟性が高い傾向にあります。
- 環境:Javaは仮想マシンやブラウザで動作させることにより、基本的にどのような環境でも使用できますが、JavaScriptはブラウザのみで機能します。
- メモリ使用量:JavaはJavaScriptに比べてメモリ使用量が多く、WebページやWebアプリケーションにはJavaScriptが適しています。
JavaScriptは安全なのか
JavaScriptは広く普及し、Web開発に利用されていますが、脆弱性もあります。JavaScriptの脆弱性を利用したサイバー攻撃の代表的なものに、クロスサイトスクリプティング(XSS)攻撃があり、XSS攻撃の利用から、個人情報の盗難が試みられます。脆弱性の利用を最小限に抑えるためには、開発中にコードをテストし、審査することが重要です。静的アプリケーション・セキュリティ・テストや動的アプリケーション・セキュリティ・テスト(SASTやDAST)などは、ソフトウェア開発ライフサイクルのすべての段階で脆弱性を特定するのに効果的です。Cloud Defense社のセキュリティアナリストによると、SASTは、コードがセキュリティルールに違反していないかどうかをチェックし、発見された脆弱性をソースブランチとターゲットブランチの間で比較します。そして、プロジェクトの依存関係が、新たに開示された脆弱性の影響を受けている場合には、通知を受け取ることができます。
Vanilla JavaScript
Vanilla JavaScriptとは、純粋なJavaScript言語(ライブラリを追加していない状態)です。ここでいう「Vanilla」とは、カスタマイズされていないJavaScriptのことを指します。Google、Microsoft、Apple、Amazonなど、多くの大手企業がVanilla JSを採用しています。Vanilla JavaScriptは、ライブラリのより高度な機能を利用し始める前にJavaScriptプログラミングの基礎を学ぶのにも便利です。
JavaScriptライブラリ
JavaScriptライブラリは、特定の機能を実行するために用意されたコードのまとまりです。ライブラリを利用することで、初心者の方でもサイトを素早く構築することができます。また、初心者でも経験豊富な人でも、サイトやアプリケーションの構築にかかる時間を大幅に短縮できます。JavaScriptライブラリは数多くありますが、代表的なものとしては、jQuery、Anime.js、Animate on Scroll、Leaflet.jsなどがあります。
JavaScriptとウェブサイトフレームワークとの関係
ウェブサイトフレームワークは、高度なサイト構築ツールで、通常、これには、機能やテストスイートが組み込まれています。サーバーサイドのフレームワークでは、Laravel、Ruby on Rails、Djangoなどが有名どころです。また、React.js、Vue.js、Node.jsなど、クライアントサイドのJavaScriptベースのフレームワークも人気があります。
JavaScript DOM
DOM(Document Object Model)は、JavaScriptなどのプログラミング言語と、基礎となるドキュメント(具体的には、HTMLやXMLドキュメント)との間のインターフェースとして機能します。DOMはW3C(World Wide Web Consortium)の標準規格で、「プログラムやスクリプトがドキュメントのコンテンツ、構造、スタイルに動的にアクセスし、更新することを可能にする、プラットフォームや言語に依存しないインターフェース」と定義されています。ドキュメントは、個々の要素やプロパティ(テキスト、ボタン、リンクなど)の集まりで構成されます。
JavaScriptの基本コンポーネント
他のプログラミング言語と同様に、JavaScriptはデータの保存場所を特定するのに変数を使用します。変数には、グローバル(コード内のどの関数からでもアクセス可能)なものと、ブロックスコープと呼ばれるローカル(宣言されたブロック内でのみアクセス可能)なものがあります。変数には、固定値(リテラルと呼ばれる定数)と変更可能な値があります。JavaScriptには、定数や変数を宣言(作成)し、値を代入するための特別な構文があります。
定数の宣言
真の定数は、const
を使用して作成します。Const
は、読み取り専用、変更不可、ブロックスコープ付きの定数を作成します(「ブロックスコープ付き」とは、宣言したブロックの外からは定数にアクセスできないことを意味します)。const を使用して定数を作成する例を以下に示します。
const GOLDEN_RATIO = 1.618; // create a constant named GOLDEN_RATIO with value 1.618
定数の名前には大文字を使いますので、ご注意ください。これは、必須ではありませんが、広く浸透している原則です。変数名(定数名を含む)は、アルファベット(小文字または大文字)、アンダースコア(_
)、ドル記号($
)のいずれかで始めなければなりません。大文字と小文字は区別されますので、変数名の表記にご注意ください。定数は、変数とは異なり、作成時に値を割り当てる必要があります。次のような記述はエラーになります。
const GOLDEN_RATIO;
Declaring a Variable 変数の宣言
変数は、var
を使って宣言します。宣言時に値を入れる必要はありませんが、指定しても構いませんし、実際には頻繁にそうされています。var
は、ブロックスコープではなくグローバルスコープとなります(ただし、関数の中にある場合には、関数スコープを持ちます)。
var variable1; // declare a variable called variable1
var variable2 = "2021"; // declare a string variable called variable2 and initialize with value 2021
variable1 = "Thank goodness it's" // assign string value to previously declared variable variable1
console.log(variable1 + " " + variable2); // display "Thank goodness it's 2021"
JavaScriptのステートメントはセミコロンで終わる必要がありますので、ご注意ください。JavaScriptでは、//
でコメントを挿入でき、//
と行末の間にある全てがコードから除外されます。変数には、数値、文字列、オブジェクトなど、さまざまなデータ型を利用できます。JavaScriptにおける変数の割り当ては動的です。そのため、同じコード内で、変数を様々なデータ型に割り当てることができます。
巻き上げ
JavaScriptにおける変数の宣言について理解したところで、次にJavaScriptで、どのように変数の宣言の場所が扱われているか見てみましょう。一般的なコーディングの手法として、変数を定義する前、または定義すると同時に宣言します。いくつかのプログラミング言語では、必須です。しかし、JavaScriptでは、変数を定義したり使用したりした後に宣言することができます。JavaScriptでは、巻き上げというものを使って、宣言をそのスクリプトや関数の先頭に移動可能です。巻き上げを用い、宣言の失敗を手軽に修正できますが、使用後に変数を宣言する行為は、プログラミングのベストプラクティスとは言えません。また、巻き上げは宣言にのみ適用されるため、予期せぬ問題を引き起こす可能性があります。変数の宣言と初期化が同じステートメントで行われるケースを考えてみると、巻き上げによりブロックの先頭に宣言が作成され、変数に未定義の値が割り当てられることになります。したがって、実際の宣言文の前のブロックでその変数を使用すると、その変数は初期化値ではなく未定義であるとみなされます。上の例を使って、巻き上げの挙動を確認してみましょう。
var variable_1 = "Thank goodness it's"; // declare and initialize a string variable called variable_1
console.log(variable_1 + " " + variable_2); //
var variable_2 = "2021" // declare and initialize a string variable called variable2
巻き上げは、variable_2
の宣言をブロックの先頭に動かしますが、割り当てられた値は移動しません。これは、次とほぼ同じ動きをします。
var variable_1 = "Thank goodness it's"; // declare and initialize a string variable called variable_1
var variable_2;
console.log(variable1 + " " + variable2); //
variable_2 = "2021" // assign string value to variable2
いずれのパターンであっても、最終的な値「Thank goodness it’s 2021」は出力に含まれません。潜在的な問題を回避し、クリーンなコードを目指すという意味で、変数宣言のベストプラクティスを優先することをお勧めします。
オブジェクト
JavaScriptは、オブジェクトの概念に基づいています。オブジェクトは、プロパティやメソッド、あるいはその両方を内包することのできるコンテナです。簡単な例を考えてみましょう。「country」という名前のオブジェクトがあります。そのプロパティには、名前、大陸、首都、人口があります。JavaScriptでこのオブジェクトを作成する方法は、いくつかあります。まず、オブジェクトリテラルまたはオブジェクト初期化子が利用できます。
var country = {
name:"France",
continent:"Europe",
capital:"Paris",
population:62250000;
}
また、オブジェクトをインスタンス化してから、そのプロパティを割り当てることもできます。
var country = new Object();
country.name = "France";
country.continent = "Europe";
country.capital = "Paris";
country.population = 62250000;
なお、オブジェクトのプロパティを参照するには、object.property
という構文を使います。最後に、コンストラクタ関数を使ってオブジェクトを作成することができます。
function country(name, continent, capital, population) {
country.name = name;
country.continent = continent;
country.capital = capital;
country.population = population;
}
オブジェクトのインスタンスを作成するには、次のようにします。
france = new country("France","Europe","Paris",62250000)
オブジェクトのプロパティには、変数と関数があります。後述しますが、オブジェクトのプロパティが関数の場合は、メソッドと呼ばれます。
オブジェクト VS クラス
一言で言えば、クラスはオブジェクトの汎用的な構造テンプレートです。クラスは、コンストラクタ形式でオブジェクトを記述します。
class country {
Constructor (name,continent,capital,population) {
country.name = name;
country.continent = continent;
country.capital = capital;
country.population = population;
}
}
オブジェクトと同じように、クラスはメソッドを持ち得ます。
定数と変数の使用
他の言語と同様に、JavaScriptには、変数や関数に使用する複数種類の演算子があり、そのほとんどはすぐに理解できるはずです。
- 代入演算子 (
=
,+=
,-=
,*=
,/=
,%=
) - 比較演算子 (
==
,===
,!=
,!==
,>
,>=
,<
,<=
) - ビット/論理演算子 (後述)
- 算術演算子 (
+
,-
,*
,/
,%
,++
,--
) - 特別な演算子
厳密等価演算子や厳密不等価演算子など、初心者プログラマーにはあまりなじみのない演算子もあります。「===
」は、2つのオペランドが同じ値と型の両方を持っているかどうか(つまり、同一であるかどうか)を比較します。「!==
」は、2つのオペランドが同一でないかどうかを比較します。次のような例を考えてみましょう。
var variable_1 = 5; // declare variable_1 and assign numeric value 5
var variable_2 = "5"; // declare variable_2 and assign string value "5"
console.log(variable_1 === variable_2);
console.log(variable_1 !== variable_2);
このコードの出力は次のようになります。
FALSE
TRUE
また、「=
」(代入演算子)と「==
」(比較演算子)の違いについても理解しておく必要があります。「=
」が変数の値を設定するのに対し、「==
」は2つのオペランドが同じ値を持つかどうかをチェックするもので、変数が与えられた値を持つかどうかもこれに含まれます。IF文などの条件文では、等価性を確認するために「=
」演算子を使ってはいけません。
ビット/論理演算子
JavaScriptは、AND(&
)、OR(|
)、NOT(~
)、XOR(^
)の各演算をサポートしています。JavaScriptでは、これらはビット演算子と呼ばれます。ビット演算では、演算子を32ビットのバイナリ表現に変換してから演算を行います(例:20が10100になる)。このような演算は、変換されたオペランドをビットごとに比較し、整数に変換された32ビットのバイナリを返すことから、ビット演算と呼ばれています。例は次の通りです。
var variable_1 = 20;
var variable_2 = 50;
console.log(variable_1 | variable_2) // display the result of variable_1 OR variable_2
オペランドをバイナリに変換します。
20 = 010100
50 = 110010
OR演算は、どちらかのビットが1のときに真(1)を返すので、表示される比較値は「110110」または「53」となります。JavaScriptでは、オペランドにおいて、ブーリアンの値が0または1である演算を論理演算子と呼びます。JavaScriptの論理演算子は、「&&
(論理AND)」、「||
(論理OR)」、「!
(論理NOT)」です。
var variable_1;
var variable_2;
variable _1 = (6 > 5); // sets variable_1 to true or 1
variable_2 = (7 <= 6); // sets variable_2 to false or 0
Console.log(variable_1 && variable_2); // displays 0
関数とメソッド
関数は、JavaScriptの主力機能です。関数は、特定のタスクを実行するコードの塊です。他のプログラミング言語でプロシージャやサブルーチンに慣れ親しんでいる方なら、すぐに関数を理解できるでしょう。関数は次のような構文で定義します。
function function_name(parameter list) {
// tasks to be performed
}
関数は定義するだけでなく、()
を使って呼び出す必要があります。
$()
$()
関数は、上述したように、HTML DOMの特定の要素のIDを返す、getElementByIDメソッドの省略形です。この関数は、ドキュメント内の要素を操作する際によく使われます。$()
を使うことで、より短く、より効率的なJavaScriptのコーディングが可能になります。典型例が以下の通りです。
document.getElementByID("element_id")
$() method:
$("element_id")
関数 VS メソッド
関数はタスクを実行するもので、メソッドは関数の定義を含むオブジェクトのプロパティです。メソッドを呼び出すための構文は、object.function()
です。関数は自己完結型で、メソッドはオブジェクトに関連付けられます。上の例では、document.getElementByID("element_id")
というメソッドは、オブジェクト(document
)と、そのオブジェクトに関連するプロパティ(getElementbyID()
)を参照しています。JavaScriptには2種類のメソッドがあります。
- インスタンスメソッド
- 静的メソッド
インスタンスメソッドは、オブジェクトインスタンスのプロパティにアクセスし、これを操作することができます。インスタンスメソッドは、別のインスタンスメソッドまたは静的メソッドを呼び出すこともできます。静的メソッドは、クラスのインスタンスではなく、クラスに関連する論理を含みます。静的メソッドを作成するには、関数定義の前に static という単語を使用する必要があります。静的メソッドは、静的フィールドにのみアクセスでき、インスタンスフィールドにはアクセスできません。
JavaScriptのPromise
Promiseとは、将来に特定の結果をもたらすオブジェクトのことです。JavaScriptの用語では、Promiseはコードの「プロデュース」と「コンシューム」と呼ばれます。関数は、完了までに不特定かつ多大な時間を要することがあります。コードのコンシュームとなると、非同期の「プロデュース」コードの結果を待ってから、その関数を実行します。プロデュースコードとコンシュームコードの関係を定義するのがPromiseです。Promiseには「保留」、「履行」、「拒否」の3つの状態があります。Promiseの定義では、「resolve」と「reject」の2つの引数が指定されます。「保留」はPromiseの初期状態で、Promiseが「履行」されても「拒否」されてもいないことを意味します。「履行」は、Promiseが解決されたことを意味します。「拒否」は、文字通り、そのPromiseが拒否されたことを意味します。保留状態でなくなったPromiseは、解決済みとみなされます。Promiseを作成する構文は、例えば、次のとおりです。
var newPromise = new Promise(
function(resolve, reject) {
// condition to be tested
}
)
JavaScriptのクロージャ
クロージャは、それほど複雑ではありませんが、プログラマーが困惑しがちなJavaScriptの機能です。JavaScriptでは、クロージャを使って、入れ子になった関数の操作に対処できます。具体的には、クロージャを使うと、通常からアクセス可能なグローバル変数に加え、内側の関数が親関数の中身にアクセスできるようになります。ちなみに、内側の関数が外側の関数の変数にアクセスできますが、その逆はできませんのでご注意ください。クロージャを理解するには、スコープの基本をおさえておく必要があります。関数内の変数は、通常、その関数からしかアクセスできません。また、スコープは、その関数に対して汎用的に作られるのではなく、呼び出しごとに作られます。クロージャは、「関数完了に伴い変数が消えてしまう」という特徴に対処するためのものです。また、関数実行後でも、変数にアクセスできるようになります。次のようなコードの例を考えてみましょう。
function outer_closure_function() {
var outer_variable = "we want to keep the outer variable";
var inner_closure_function = function() {
inner_variable = "use closures because"
console.log(inner_variable + " " + outer_variable);
}
return inner_closure_function;
}
var closure = outer_closure_function(); // returns a reference to inner_closure_function
closure(); // displays "use closures because we want to keep the outer variable"
クロージャの仕組みを理解するために、コードを1行ずつ見ていきましょう。まず、外側の関数を定義し、その関数に関連する変数を定義します。次に、内側の関数を定義します。重要なのは、内側の関数を呼び出していないことです─定義しただけの状態です。次に、内側の関数を返すステートメントを記述します。しかし、これが返すのは内側の関数の結果ではなく、関数そのものです。つまり、クロージャをouter_closure_function
と定義しても、内側の関数の実際の値を返すわけではありません。代わりに、inner_closure_function
の参照が返されます。この文の後に外側の関数が完成して、正式にはouter_variable
が存在しなくなっているにもかかわらず、このような挙動になります。しかし、これは、inner_closure_function
の参照の中にまだ存在しています。これで、最後のステートメントでクロージャを呼び出すと、期待通りの結果が表示されます。クロージャの理解を深めるには、自分でサンプルをコーディングしてみるのが一番です。正しく理解できるまでには、時間がかかります。さらに、更新とテストを繰り返すことで、アジャイル開発のマインドセットを手にすることができるはずです。しかし、その際には、セキュリティもお忘れ無く。JavaScriptは、SQLやLDAPインジェクション、XSS攻撃など、深刻な問題に対して脆弱になりがちです。
まとめ
もし、WixやSquareといったすぐに使えるサービスではできないようなことを、自分のサイトで実装したいのであれば、JavaScriptを学習してみるのがいいかもしれません。JavaScriptでは、ウェブサイトやアプリケーションのプログラミングをシンプルかつ簡単に学ぶことができ、学習プロセスに多くの時間を費やすことなく、サイトに高度にインタラクティブな機能を追加することができます。また、JavaScriptは、コーディングのスキルアップという意味でもおすすめです。