JavaScriptの基礎をまとめた備忘録
JavaScript基礎
JavaScriptは、動的で柔軟な言語であり、Web開発に広く使用されています。
JavaScriptの基礎となる概念を以下に示します。
- 変数:JavaScriptでは、値を保存するために変数を使用します。変数を宣言するには、var、let、またはconstを使用します。
- データ型:JavaScriptには、プリミティブ型(数値、文字列、真偽値、null、undefined)とオブジェクト型(配列、関数、オブジェクト)の2つのデータ型があります。
- 制御構造:JavaScriptには、条件分岐(if、else if、else)、ループ(for、while)、switch文などの制御構造があります。
- 関数:JavaScriptでは、関数を定義して再利用可能なコードを作成できます。関数には引数と戻り値があります。
- イベント:JavaScriptを使用して、ユーザーのアクション(クリック、マウスオーバー、キーボード入力など)に対する処理を記述できます。
- オブジェクトとプロパティ:JavaScriptでは、オブジェクトを使用して関連するデータをグループ化できます。オブジェクトには、プロパティと値があります。
- クラス:ES6以降、JavaScriptにはクラスが導入され、オブジェクト指向プログラミングがサポートされました。
- DOM:JavaScriptを使用して、HTML要素の取得、追加、削除、変更など、Webページのドキュメントオブジェクトモデル(DOM)を制御できます。
1. 変数
JavaScriptには、変数を使ってデータを保持することができます。
変数キーワード
変数はvar, let, constキーワードを使って宣言します。
var text = "sample text";
let message = "Hello, World!";
const pi = 3.14159;
var
varは、ES5以前のJavaScriptで利用されていた変数宣言のキーワードです。
varで宣言した変数は、スコープが関数レベルのため、関数の内側で宣言された変数は、関数内でのみアクセス可能です。
また、varで宣言された変数は、同じ名前の変数を再度宣言できてしまい、変数の値を上書きできてしまいます。
function myFunction() {
var x = 1;
if (true) {
var x = 2;
console.log(x); // 2
}
console.log(x); // 2
}
myFunction();
let
letは、ES6で導入されたブロックレベルのスコープを持つ変数宣言のキーワードです。
letで宣言された変数は、そのブロック内でのみアクセス可能です。
また、同じ名前の変数を再度宣言することはできませんが、変数の値を再代入することができます。
function myFunction() {
let x = 1;
if (true) {
let x = 2;
console.log(x); // 2
}
console.log(x); // 1
}
myFunction();
const
constは、ES6で導入されたブロックレベルのスコープを持つ定数宣言のキーワードです。
constで宣言された変数は、そのブロック内でのみアクセス可能です。
また、同じ名前の変数を再度宣言することはできませんし、再代入もできません。定数を宣言する場合に使用します。
function myFunction() {
const x = 1;
if (true) {
const x = 2;
console.log(x); // 2
}
console.log(x); // 1
}
myFunction();
ただし、オブジェクトや配列といった参照型のデータをconstで宣言した場合でも、その値を再代入することはできませんが、オブジェクトや配列自体のプロパティを変更することはできます。
const person = { name: "John", age: 30 };
person.age = 40; // OK
person = { name: "Alice", age: 20 }; // エラー
変数宣言
変数を宣言するときには、初期値を設定する必要はありませんが、
変数を使用する前に初期値が設定されている必要があります。
初期値が設定されていない場合、変数の値は undefined
になります。
let myVar;
console.log(myVar); // undefined
myVar = 10;
console.log(myVar); // 10
2. データ型
JavaScriptには、以下のようなデータ型があります。
文字列: "Hello, World!"
数値: 42
真偽値: trueまたはfalse
undefined: 変数に値が割り当てられていない状態
null: 変数にnullという値を明示的に代入した状態
オブジェクト: { name: "John", age: 30 }
配列: [1, 2, 3]
以下、それぞれのデータ型について説明します。
文字列
文字列は、文字や記号の集合を表します。
文字列は、シングルクォーテーション'
または ダブルクォーテーション"
で囲みます。
また、バッククォート``を使用すると、複数行にわたる文字列を表現することができます。
let name = "Alice";
let message = "Hello, " + name + "!";
let multiLine = `Hello,
World!`;
数値
数値は、整数や小数点以下の数を表します。
let x = 42;
let y = 3.14;
真偽値
真偽値は、trueまたはfalseの値を表します。
真偽値は、比較演算子や論理演算子の結果として返されることが多いです。
let x = 5;
let y = 10;
let result = x < y; // true
undefined
undefinedは、変数に値が割り当てられていない状態を表します。
未定義の変数を参照した場合、その変数はundefinedになります。
let x;
console.log(x); // undefined
null
nullは、変数にnullという値を明示的に代入した状態を表します。
let x = null;
console.log(x); // null
オブジェクト
オブジェクトは、キーと値のペアで構成される複合データ型です。
オブジェクトは、波括弧{}
で囲んで表現します。
let person = { name: "John", age: 30 };
console.log(person.name); // John
console.log(person.age); // 30
配列
配列は、複数の値を順番に格納することができます。
配列は、 角括弧[]
で囲んで表現します。
let fruits = ["apple", "banana", "orange"];
console.log(fruits[0]); // apple
console.log(fruits[1]); // banana
console.log(fruits[2]); // orange
3. 制御構造
JavaScriptには、制御構造と呼ばれる文法があります。
これらの構造を使用することで、条件分岐や繰り返し処理を行うことができます。
条件分岐
if文
if文は、条件式がtrueの場合に、指定された文を実行する制御構造です。
if (条件式) {
// 条件式が true の場合に実行する文
}
if-else文
if-else文は、条件式がtrueの場合には指定された文を実行し、そうでない場合には別の文を実行する制御構造です。
if (条件式) {
// 条件式が true の場合に実行する文
} else {
// 条件式が false の場合に実行する文
}
else-if文
else-if文は、複数の条件式を判定するために使用され、最初にif文が評価され、その後の条件が評価されます。
if (条件式1) {
// 条件式1が true の場合に実行する文
} else if (条件式2) {
// 条件式2が true の場合に実行する文
} else if (条件式3) {
// 条件式3が true の場合に実行する文
} else {
// いずれの条件式も false の場合に実行する文
}
三項演算子
三項演算子は、条件分岐を1行で書くことができます。
以下のような構文になります。
条件式 ? trueの場合の文 : falseの場合の文
例えば、次のような式は、xが10以下の場合は'10以下'を返し、そうでない場合は'10より大きい'を返します。
var result = x <= 10 ? '10以下' : '10より大きい';
三項演算子を使用すると、簡潔で読みやすいコードを書くことができますが、
ネストが深くなると可読性が悪くなることがあるため、注意が必要です。
繰り返し処理
while文
while文は、指定された条件がtrueである限り、繰り返し処理を行う制御構造です。
以下の構文を持ちます。
while (条件式) {
// 繰り返し実行する文
}
例えば、1から10までの数値を順番に表示する場合、以下のように書くことができます。
var i = 1;
while (i <= 10) {
console.log(i);
i++;
}
do-while文
do-while文は、while文と似ていますが、条件式の評価が後ろに来る点が異なります。つまり、最初に1回だけ繰り返し処理を行い、その後に条件式を評価します。
以下の構文を持ちます。
do {
// 繰り返し実行する文
} while (条件式);
例えば、1から10までの数値を順番に表示する場合、以下のように書くことができます。
var i = 1;
do {
console.log(i);
i++;
} while (i <= 10);
do-while文は、繰り返し処理を最低でも1回は行う必要がある場合に便利です。
for文
for文は、指定された回数だけ繰り返し処理を行う制御構造です。
以下の構文を持ちます。
for (初期化式; 条件式; 更新式) {
// 繰り返し実行する文
}
- 初期化式: 繰り返し処理を開始する前に1回だけ実行される式です。一般的には、カウンター変数を初期化するために使用されます。例えば、var i = 0;のように記述します。
- 条件式: 繰り返し処理が継続されるかどうかを判定するための式です。条件式がtrueの場合、繰り返し処理が実行されます。例えば、i < 10のように記述します。
- 更新式: 繰り返し処理の最後に1回だけ実行される式です。一般的には、カウンター変数を更新するために使用されます。例えば、i++のように記述します。
例えば、1から10までの数値を順番に表示する場合、以下のように書くことができます。
for (var i = 1; i <= 10; i++) {
console.log(i);
}
for-in文
for-in文は、オブジェクトのプロパティを列挙するためのループです。以下の構文を持ちます。
for (var 変数名 in オブジェクト) {
// プロパティに対する処理
}
for-in文は、オブジェクトのキー(プロパティ名)を順番に取り出して、そのキーに対応する値にアクセスします。
例えば、以下のように記述します。
var obj = { a: 1, b: 2, c: 3 };
for (var key in obj) {
console.log(key, obj[key]);
}
この場合、objオブジェクトのキーを順番に取り出して、そのキーに対応する値を表示します。
結果は、以下のようになります。
a 1
b 2
c 3
注意点として、for-in文は、オブジェクトのプロトタイプチェーンも列挙するため、予期しない動作を引き起こすことがあります。
そのため、オブジェクトのプロパティを列挙する場合は、 hasOwnProperty()メソッド
を使用して、プロトタイプチェーンを排除することが推奨されています。
for-of文
for-of文は、配列や文字列などの反復可能なオブジェクトを繰り返し処理するためのループです。
以下の構文を持ちます。
for (var 変数名 of 反復可能なオブジェクト) {
// 要素に対する処理
}
for-of文は、配列や文字列などの要素を順番に取り出して、その要素に対応する値にアクセスします。
例えば、以下のように記述します。
var arr = [1, 2, 3];
for (var value of arr) {
console.log(value);
}
この場合、arr配列の要素を順番に取り出して、その値を表示します。
結果は、以下のようになります。
1
2
3
for-of文は、反復可能なオブジェクトに対してしか使用できないため、オブジェクトの場合はfor-in文を使用する必要があります。
また、for-of文は、ECMAScript 6から導入されたため、古いブラウザでは動作しません。
4. 関数
JavaScriptにおける関数は、プログラムの中で繰り返し利用される処理をまとめたもので、再利用性や可読性を高めるために使われます。
関数は、以下のように定義します。
function 関数名(引数1, 引数2, ...) {
// 処理
return 戻り値;
}
ここで、関数名は関数の名前、引数1、引数2などは関数に渡す引数の名前であり、処理は関数内で実行される処理、戻り値は関数から返される値です。
以下は、簡単な足し算を行う関数の例です。
function add(a, b) {
return a + b;
}
var result = add(1, 2); // 3
この関数を呼び出すと、引数に渡した2つの数値を足した結果が返されます。
また、関数は変数に代入することもできます。これを 無名関数(匿名関数)
と呼びます。
var add = function(a, b) {
return a + b;
};
var result = add(1, 2); // 3
関数の中で定義された変数は、関数の外からアクセスすることができません。これをスコープと呼びます。スコープについては、関数スコープとブロックスコープの2つがあります。
関数スコープは、関数内で定義された変数が関数内でのみ有効で、関数外からはアクセスできないことを指します。
一方、ブロックスコープは、ブロック({})内で定義された変数が、そのブロック内でのみ有効で、ブロック外からはアクセスできないことを指します。
しかし、ES6からはletやconstといったブロックスコープの変数定義方法が導入され、より細かいスコープの定義が可能になりました。
また、関数は、他の関数の中で定義することもできます。これをネストした関数と呼びます。
ネストした関数は、外側の関数のスコープにアクセスできるため、外側の関数で定義された変数を参照することができます。
以下は、ネストした関数の例です。
function outer() {
var a = 1;
function inner() {
var b = 2;
return a + b;
}
return inner();
}
var result = outer(); // 3
この例では、outer関数の中でaという変数が定義され、inner関数の中でbという変数が定義されています。
inner関数はa + bを返すため、outer関数を呼び出すと、3が返されます。
また、関数はオブジェクトの一種であるため、関数にもプロパティを持つことができます。
以下は、関数にプロパティを追加する例です。
function add(a, b) {
return a + b;
}
add.name; // "add"
add.description = "This function returns the sum of two numbers.";
add.description; // "This function returns the sum of two numbers."
ここでは、nameプロパティには関数の名前が、descriptionプロパティには関数の説明文が追加されています。
プロパティは、ドット演算子またはブラケット演算子を使ってアクセスすることができます。
アロー関数
JavaScriptには、アロー関数と呼ばれる、短くシンプルな関数を記述するための構文があります。
アロー関数は、functionキーワードを使用せずに、矢印 =>
を使って定義されます。
以下は、アロー関数の例です。
// 通常の関数の定義
function add(a, b) {
return a + b;
}
// アロー関数による同じ関数の定義
const add = (a, b) => {
return a + b;
}
アロー関数は、通常の関数と同様に、引数を受け取り、処理を実行し、結果を返すことができます。
また、引数が一つしかない場合は、引数リストの丸括弧を省略することができます。
const square = x => {
return x * x;
}
square(5); // 25
さらに、アロー関数が単一の式である場合、中括弧とreturnキーワードを省略することができます。
この場合、式の評価結果が自動的に関数の戻り値になります。
// アロー関数による同じ関数の定義(短縮版)
const add = (a, b) => a + b;
// アロー関数による同じ関数の定義(引数が1つの場合の短縮版)
const square = x => x * x;
アロー関数は、関数の定義を簡潔にし、コードを読みやすくするために頻繁に使用されます。
ただし、アロー関数が持つthisの挙動は通常の関数と異なるため、注意が必要です。
詳細については、thisキーワードに関する知識が必要です。
thisキーワード
JavaScriptのthisキーワードは、関数が呼び出されたときに、その関数を呼び出したオブジェクトを参照するために使用されます。
thisは、関数内で使用される場所やコンテキストによって異なる値を持つことがあります。
以下は、thisキーワードの例です。
const person = {
name: "Alice",
sayHello: function() {
console.log(`Hello, my name is ${this.name}.`);
}
}
person.sayHello(); // "Hello, my name is Alice."
上記の例では、thisキーワードは、personオブジェクトを参照します。
つまり、sayHelloメソッドを呼び出すときに使用されたオブジェクトです。
しかし、thisキーワードは、functionキーワードで定義された関数内では、グローバルオブジェクトを参照します。
function sayHello() {
console.log(`Hello, my name is ${this.name}.`);
}
const person = {
name: "Alice",
sayHello: sayHello
}
sayHello(); // "Hello, my name is undefined." (this.name はグローバルオブジェクトに定義されていないため undefined)
person.sayHello(); // "Hello, my name is Alice."
また、アロー関数内でのthisの値は、アロー関数が定義されたコンテキストによって決まります。アロー関数内でのthisは、アロー関数が定義された時点でのthisと同じになります。
const person = {
name: "Alice",
sayHello: function() {
const innerFunction = () => {
console.log(`Hello, my name is ${this.name}.`);
}
innerFunction();
}
}
person.sayHello(); // "Hello, my name is Alice."
上記の例では、innerFunctionはアロー関数で定義されており、その中でのthisは、personオブジェクトを参照します。
これは、アロー関数が定義されたコンテキストであるsayHelloメソッドのthisがpersonオブジェクトであるためです。
5. イベント
JavaScriptにおけるイベントは、Webページのユーザーインタラクションに応答して実行されるコードの断片です。
イベントは、ボタンクリック、マウスオーバー、フォーム送信、ページ読み込みなどのアクションに関連して発生します。
イベントの種類
JavaScriptで使用できる一般的なイベントには、以下のものがあります。
- click: 要素がクリックされたときに発生するイベントです。例えば、ボタンがクリックされたときや、リンクがクリックされたときに使用されます。
- mouseover: 要素がマウスオーバーされたときに発生するイベントです。マウスが要素の上に移動するときに使用されます。
- mouseout: 要素からマウスが離れたときに発生するイベントです。マウスが要素の外に移動するときに使用されます。
- keydown: キーボードのキーが押されたときに発生するイベントです。キーが押された状態を検知したい場合に使用されます。
- keyup: キーボードのキーが離されたときに発生するイベントです。キーが離された状態を検知したい場合に使用されます。
- input: テキストボックスやテキストエリアなどの入力要素の値が変更されたときに発生するイベントです。入力された値を取得したい場合に使用されます。
- submit: フォームが送信されたときに発生するイベントです。フォームの送信前に処理を実行するなどの場合に使用されます。
イベントリスナーの追加
イベントを処理するために、イベントリスナーを追加する必要があります。これは、DOM要素に対して行われます。
DOM要素には、HTMLのボタン、リンク、テキストボックスなどが含まれます。イベントリスナーは、addEventListener()メソッドを使用して追加されます。
以下は、ボタンクリックイベントの例です。
<input type="button" value="Button" id="myButton" />
<script>
const button = document.querySelector('#myButton');
button.addEventListener('click', function() {
console.log('Button clicked!');
});
</script>
上記の例では、querySelector()メソッドを使用して、myButton IDを持つボタンを取得し、addEventListener()メソッドを使用して、clickイベントが発生した場合に実行される関数を指定しています。
イベントハンドラーの作成
イベントが発生した場合に実行される関数を作成する必要があります。これは、イベントリスナーで指定されます。
関数は、イベントが発生した場合に実行されるコードを含みます。
例えば、以下は、テキストボックスの値が変更されたときに、その値を表示するイベントハンドラーの例です。
<h2 id="view">Text box value changed to </h2>
<input type="text" id="myTextBox" />
<script>
const textBox = document.querySelector('#myTextBox');
textBox.addEventListener('input', function () {
document.querySelector('#view').innerText = `Text box value changed to ${textBox.value}`;
});
</script>
上記の例では、querySelector()メソッドを使用して、myTextBox IDを持つテキストボックスを取得し、addEventListener()メソッドを使用して、inputイベントが発生した場合に実行される関数を指定しています。
イベントの削除
イベントリスナーを削除する必要がある場合は、removeEventListener()メソッドを使用します。
<input type="button" id="myButton" value="myButton" />
<input type="button" id="eventDelete" value="eventDelete" />
<script>
const button1 = document.querySelector('#myButton');
button1.addEventListener('click', sayHello);
const button2 = document.querySelector('#eventDelete');
button2.addEventListener('click', function () {
alert("event delete");
button1.removeEventListener('click', sayHello);
});
function sayHello() {
alert("Hello");
}
</script>
上記の例では、clickイベントのリスナーを削除しています。
6. オブジェクトとプロパティ
JavaScriptにおけるオブジェクトは、関連する値と関数をグループ化したものです。
JavaScriptのオブジェクトは、{}を用いて作成することができます。
以下は、空のオブジェクトを作成する例です。
const myObj = {};
オブジェクトには、プロパティと呼ばれる値や関数を含めることができます。
プロパティは、名前と値のペアで構成されます。
プロパティ名は文字列であり、値には、文字列、数値、真偽値、オブジェクト、関数などを指定することができます。
以下は、プロパティを持つオブジェクトを作成する例です。
const myObj = {
name: 'John',
age: 30,
isStudent: false,
sayHello: function() {
console.log('Hello!');
}
};
この例では、name、age、isStudentという名前のプロパティを持ち、それぞれの値には文字列、数値、真偽値を指定しています。
また、sayHelloという名前のプロパティには、関数を指定しています。
オブジェクトのプロパティにアクセスするには、ドット(.)またはブラケット([])を使用します。
以下は、オブジェクトのプロパティにアクセスする例です。
const myObj = {
name: 'John',
age: 30
};
console.log(myObj.name); // John
console.log(myObj['age']); // 30
この例では、ドットを使用してnameプロパティにアクセスし、ブラケットを使用してageプロパティにアクセスしています。
また、プロパティに値を割り当てることもできます。
以下は、プロパティに値を割り当てる例です。
const myObj = {
name: 'John',
age: 30
};
myObj.name = 'Bob';
myObj['age'] = 40;
console.log(myObj.name); // Bob
console.log(myObj.age); // 40
この例では、nameプロパティに新しい値を割り当て、ageプロパティにも新しい値を割り当てています。
ネイティブオブジェクト
JavaScriptには、最初から用意されているネイティブオブジェクトがあります。
これらはJavaScriptのコア機能を提供し、標準の組み込みオブジェクトと呼ばれることもあります。
- Object
JavaScriptのオブジェクトの基本となるオブジェクトです。
すべてのオブジェクトは、Objectから継承されたプロパティとメソッドを持ちます。
const obj = { x: 1, y: 2 };
console.log(obj.toString()); // [object Object]
- Array
配列を操作するためのオブジェクトです。
配列の要素は、インデックス番号を用いてアクセスできます。
const arr = [1, 2, 3];
console.log(arr.length); // 3
- String
文字列を扱うためのオブジェクトです。
文字列の各文字は、インデックス番号を用いてアクセスできます。
const str = 'Hello, world!';
console.log(str.length); // 13
- Number
数値を扱うためのオブジェクトです。
数値に対して、算術演算や数値の書式設定を行うことができます。
const num = 42.195;
console.log(num.toFixed(2)); // 42.20
- Boolean
真偽値を扱うためのオブジェクトです。
真偽値に対して、論理演算を行うことができます。
const flag = true;
console.log(!flag); // false
- Date
日付と時刻を扱うためのオブジェクトです。
現在時刻を取得したり、日付の計算を行うことができます。
const now = new Date();
console.log(now.getFullYear()); // 2023
- RegExp
正規表現を扱うためのオブジェクトです。
文字列のパターンを指定して、文字列の検索や置換を行うことができます。
const str = 'JavaScript is awesome!';
const pattern = /JavaScript/g;
console.log(pattern.test(str)); // true
ユーザー定義オブジェクト
JavaScriptでは、ユーザーが独自に定義したオブジェクトを作成することができます。
これをユーザー定義オブジェクトと呼びます。
ユーザー定義オブジェクトを作成するためには、オブジェクトリテラルやコンストラクタ関数を使用することができます。
- オブジェクトリテラルを使用したユーザー定義オブジェクトの作成
オブジェクトリテラルを使用すると、以下のようにオブジェクトを定義することができます。
const user = {
name: 'John',
age: 25,
sayHello: function() {
console.log(`Hello, my name is ${this.name}.`);
}
};
この場合、userという変数にオブジェクトを代入しています。
このオブジェクトは、name、age、sayHelloというプロパティを持ちます。
また、sayHelloプロパティには関数が格納されており、オブジェクト内でのメソッドとして使用することができます。
- コンストラクタ関数を使用したユーザー定義オブジェクトの作成
コンストラクタ関数を使用すると、以下のようにオブジェクトを定義することができます。
function User(name, age) {
this.name = name;
this.age = age;
this.sayHello = function() {
console.log(`Hello, my name is ${this.name}.`);
};
}
const user = new User('John', 25);
この場合、Userというコンストラクタ関数を定義しています。
この関数は、name、age、sayHelloというプロパティを持つオブジェクトを作成するために使用されます。
new演算子を使用して、User関数からオブジェクトを生成することができます。
プロパティの種類
JavaScriptのオブジェクトには、以下のようなプロパティの種類があります。
1. オブジェクトのデータプロパティ
- 値を持つ: プロパティには値を持つことができます。
- 書き換え可能かどうかを設定できる: データプロパティには、書き換え可能かどうかを設定することができます。Object.definePropertyメソッドを使って、プロパティの属性を設定することができます。
- 列挙可能かどうかを設定できる: データプロパティには、列挙可能かどうかを設定することができます。Object.definePropertyメソッドを使って、プロパティの属性を設定することができます。
- 削除可能かどうかを設定できる: データプロパティには、削除可能かどうかを設定することができます。delete演算子を使って、プロパティを削除することができます。
以下は、データプロパティの例です。
const obj = {
name: "John",
age: 30
};
// プロパティの値を取得
console.log(obj.name); // "John"
// プロパティの値を変更
obj.age = 40;
console.log(obj.age); // 40
// 書き換え可能かどうかを設定
Object.defineProperty(obj, "name", {
writable: false
});
// プロパティの値を変更(エラーが発生する)
obj.name = "Mike"; // TypeError: Cannot assign to read only property 'name' of object '#<Object>'
console.log(obj.name); // "John"
// 列挙可能かどうかを設定
Object.defineProperty(obj, "age", {
enumerable: false
});
// for...inループでプロパティを列挙
for (let prop in obj) {
console.log(prop); // "name"
}
// 削除可能かどうかを設定
Object.defineProperty(obj, "name", {
configurable: false
});
// プロパティを削除(エラーが発生する)
delete obj.name; // TypeError: Cannot delete property 'name' of #<Object>
console.log(obj.name); // "John"
2. オブジェクトのアクセサプロパティ: getter関数とsetter関数を使って値を取得・設定するプロパティ。
- get: プロパティの値を取得するための関数。
- set: プロパティの値を設定するための関数。
- enumerable: プロパティが列挙可能かどうかを示すフラグ。
- configurable: プロパティが削除、再定義可能かどうかを示すフラグ。
以下は、JavaScriptのアクセサプロパティの例です。
const obj = {
get myProp() {
return this._myProp;
},
set myProp(value) {
this._myProp = value;
}
};
obj.myProp = "hello";
console.log(obj.myProp); // 出力結果: "hello"
この例では、オブジェクトobjにmyPropというアクセサプロパティを定義しています。
アクセサプロパティは、getおよびsetキーワードで定義されたゲッターとセッター関数によって実装されます。
get関数はプロパティ値を取得し、set関数はプロパティ値を設定します。
アクセサプロパティは、データプロパティとは異なり、プロパティ値を直接格納するのではなく、関数を介してプロパティ値を取得および設定します。
また、アクセサプロパティには、プロパティ値を保持するためのプロパティにアクセスするために使用される識別子が必要です。
上記の例では、_myPropという識別子が使用されています。これは、アクセサプロパティの内部的なストレージ変数として機能します。
3. 内部プロパティ
JavaScriptの内部プロパティは、JavaScriptエンジンによって暗黙的に生成され、JavaScriptコードからは直接アクセスできないプロパティであり、オブジェクトの動作に必要不可欠な情報を保持しています。
- [[Prototype]]: オブジェクトのプロトタイプを指定するための内部プロパティ。
- [[Class]]: オブジェクトのクラスを表すための内部プロパティ。
- [[Extensible]]: オブジェクトが拡張可能かどうかを示すための内部プロパティ。
- [[Get]]: オブジェクトのプロパティの値を取得するための内部プロパティ。
- [[Put]]: オブジェクトのプロパティの値を設定するための内部プロパティ。
- [[HasProperty]]: オブジェクトが指定されたプロパティを持つかどうかを示すための内部プロパティ。
- [[Delete]]: オブジェクトのプロパティを削除するための内部プロパティ。
- [[Call]]: 関数オブジェクトの呼び出しに使用される内部プロパティ。
- [[Construct]]: コンストラクタ関数からオブジェクトを生成するための内部プロパティ。
- [[Iterator]]: オブジェクトを反復処理するための内部プロパティ。
4. 内部メソッド
内部メソッドは、JavaScriptのエンジンによって自動的に実行されるものであり、通常のJavaScriptのコードからは直接アクセスすることができません。
しかし、オブジェクトのプロパティにアクセスする際や、関数やクラスを定義する際には、これらの内部メソッドが使用されているということを知っておくと、より深い理解が得られます。
- [[Get]]: オブジェクトのプロパティ値を取得するためのメソッド
- [[Set]]: オブジェクトのプロパティ値を設定するためのメソッド
- [[OwnPropertyKeys]]: オブジェクトの自身のプロパティキーを取得するためのメソッド
- [[Call]]: 関数オブジェクトが呼び出された際に実行されるメソッド
- [[Construct]]: クラスオブジェクトがインスタンス化された際に実行されるメソッド
5. プロトタイププロパティ
JavaScriptのプロトタイププロパティは、オブジェクトが他のオブジェクトを継承するために使用されます。
具体的には、JavaScriptオブジェクトは、prototypeプロパティを持っています。
このprototypeプロパティは、オブジェクトの親オブジェクトのプロパティを含むオブジェクトを参照します。
これにより、オブジェクトは、自身が持つプロパティだけでなく、親オブジェクトのプロパティも参照できます。
prototypeプロパティは、以下のような場合に使用されます。
- プロトタイプベースの継承:子オブジェクトが親オブジェクトのプロパティを継承する場合、子オブジェクトのprototypeプロパティは親オブジェクトのオブジェクトを参照します。
- オブジェクトの作成:new演算子を使用してオブジェクトを作成する場合、新しいオブジェクトはprototypeプロパティを持つ親オブジェクトを継承します。
- プロトタイプチェーン:オブジェクトがプロパティを探すとき、prototypeプロパティに指定されたオブジェクトを再帰的に探し、プロパティが見つかるか、最後の親オブジェクトに到達するまで、探索を続けます。
JavaScriptには、オブジェクトのprototypeプロパティに加えて、__proto__プロパティがあります。
__proto__プロパティは非標準のプロパティですが、オブジェクトのprototypeプロパティを参照するために使用されます。
__proto__プロパティは、親オブジェクトのprototypeプロパティを指すことがあります。
しかし、__proto__プロパティを使用する代わりに、Object.getPrototypeOf()メソッドを使用することが推奨されています。
6. 静的プロパティ: クラスに直接定義されたプロパティ。クラスから直接アクセスすることができる。
JavaScriptにおいて、静的プロパティは、クラス自体に関連付けられたプロパティであり、インスタンス化されたオブジェクトには含まれません。
静的プロパティは、ES6以降のクラス構文を使用して定義されます。
静的プロパティは、次のように定義されます。
class MyClass {
static myStaticProp = "hello";
}
または、ES6以前の構文を使用して次のように定義されます。
function MyClass() {
// constructor
}
MyClass.myStaticProp = "hello";
静的プロパティは、クラス名を使用してアクセスされます。
console.log(MyClass.myStaticProp); // "hello"
プロトタイプオブジェクト
JavaScriptのオブジェクトは、プロトタイプと呼ばれる別のオブジェクトと関連付けることができます。
プロトタイプオブジェクトは、オブジェクトが持つメソッドやプロパティのデフォルト値を定義するために使用されます。
すべてのオブジェクトは、プロトタイプチェーンを介して、一連のプロトタイプオブジェクトに関連付けられています。
プロトタイプチェーンは、オブジェクトに対してプロパティやメソッドが見つからない場合に、オブジェクトのプロトタイプに移動して、
そこでプロパティやメソッドを探すことを繰り返すことで構成されます。
これは、JavaScriptの継承メカニズムの基礎となっています。
JavaScriptには、すべてのオブジェクトに対して共通のプロトタイプオブジェクトがあります。
これは、Object.prototypeと呼ばれます。
Object.prototypeには、すべてのJavaScriptオブジェクトが共通で持つプロパティやメソッドが定義されています。
例えば、toString()メソッドは、Object.prototypeに定義されています。
JavaScriptでは、プロトタイプチェーンを使用して、オブジェクトを継承することができます。
オブジェクトのプロトタイプを別のオブジェクトに設定することができます。
これにより、オブジェクトが持つメソッドやプロパティのデフォルト値を変更することができます。
以下は、PersonオブジェクトのプロトタイプをHumanオブジェクトに設定する例です。
function Human(name) {
this.name = name;
}
Human.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}.`);
};
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = new Human();
const person = new Person('John', 30);
person.sayHello(); // "Hello, my name is John."
この例では、PersonオブジェクトのプロトタイプをHumanオブジェクトに設定しています。
HumanオブジェクトのsayHello()メソッドをPersonオブジェクトでも使用することができます。
また、Personオブジェクトで定義されたnameやageのプロパティは、Humanオブジェクトでも使用することができます。
内部プロパティと内部メソッド
JavaScriptのオブジェクトには、内部的に使用されるプロパティやメソッドがあります。
これらは、外部からアクセスすることはできません。
const myArray = [1, 2, 3];
console.log(myArray.length); // 3
この例では、myArrayオブジェクトのlengthプロパティにアクセスしています。
しかし、lengthは内部プロパティであり、直接アクセスすることはできません。
そのため、配列のインスタンスを作成する際に、Arrayコンストラクターのプロトタイプに定義されているlengthメソッドを継承して使用することができます。
7. クラス
JavaScriptには、ES6以降に導入されたクラスという概念があります。
クラスは、オブジェクト指向プログラミングにおける重要な概念で、関連するデータとそれらに対する操作を一つの単位にまとめることができます。
クラスは、以下のように定義します。
class MyClass {
constructor(param1, param2) {
this.prop1 = param1;
this.prop2 = param2;
}
myMethod() {
// メソッドの処理
}
}
クラスの定義は、class
キーワードに続けてクラス名を指定します。
クラス名の最初の文字は大文字にすることが一般的です。
constructorメソッドは、クラスのインスタンスを作成するときに呼び出されます。
クラスのプロパティは、thisキーワードを使用して定義します。
また、メソッドは、クラス内で定義された関数であり、クラスのプロパティにアクセスすることができます。
クラスからインスタンスを作成するには、以下のようにします。
const myInstance = new MyClass('value1', 'value2');
newキーワードを使用して、クラスのインスタンスを作成します。
このとき、constructorメソッドの引数に渡される値を指定します。
constructor
JavaScriptのクラスにおけるconstructorとは、クラスからインスタンスを生成するときに自動的に呼び出されるメソッドです。
このメソッドは、インスタンスを初期化するためのコードを含むことができます。
つまり、constructorメソッドを使うことで、クラスのインスタンスが生成された時に、そのインスタンスに初期値を設定することができます。
constructorメソッドは、以下のようにクラス内に定義します。
class MyClass {
constructor(argument1, argument2) {
// インスタンスを初期化するコード
}
}
この例では、MyClassというクラスを定義しています。
このクラスには、constructorメソッドがあり、2つの引数argument1とargument2を受け取っています。
constructorメソッド内で、インスタンスの初期化に必要なコードを書くことができます。
例えば、インスタンスのプロパティの初期化や、インスタンスメソッドの初期化などを行うことができます。
継承
JavaScriptにおけるクラスの継承とは、あるクラス(親クラス・スーパークラス)のプロパティやメソッドを別のクラス(子クラス・サブクラス)が引き継いで利用することを指します。
継承によって、親クラスで定義されたプロパティやメソッドを再利用することができ、コードの再利用性が高まります。
JavaScriptのクラスの継承は、extendsキーワードを使って実現されます。
例えば、以下のように書くことで、MyChildClassクラスがMyParentClassクラスを継承することができます。
class MyParentClass {
// 親クラスの定義
}
class MyChildClass extends MyParentClass {
// 子クラスの定義
}
この例では、MyChildClassクラスがextendsキーワードを使ってMyParentClassクラスを継承しています。
MyChildClassクラスは、MyParentClassクラスで定義されたプロパティやメソッドを自動的に引き継ぐことができます。
子クラスでは、親クラスで定義されたメソッドを上書きすることもできます。
継承によって、子クラスは親クラスのすべての非プライベートなプロパティやメソッドにアクセスすることができます。
ただし、親クラスでプライベートなプロパティやメソッドを定義した場合は、子クラスからはアクセスできなくなります。
8. DOM
DOMとは、Document Object Model(ドキュメントオブジェクトモデル)の略称で、Webページを表現するためのオブジェクトの階層的なツリー構造を指します。
JavaScriptを使って、DOMを操作することができます。
Webページは、HTML要素、テキスト、画像、リンクなどの要素から構成されています。
DOMは、これらの要素をオブジェクトとして表現し、それらのオブジェクトに対してJavaScriptでアクセスすることができます。
例えば、次のHTML要素があるとします。
<div id="myDiv">
<p>Hello, world!</p>
</div>
この要素にアクセスするためには、次のようにJavaScriptを書くことができます。
<div id="myDiv">
<p>Hello, world!</p>
</div>
<script>
// idが"myDiv"の要素を取得する
const myDiv = document.getElementById("myDiv");
// idが"myDiv"の要素の子要素であるp要素を取得する
const p = myDiv.querySelector("p");
// p要素のテキストを変更する
p.textContent = "Hello, DOM!";
</script>
表示結果は以下のようになります。
Hello, DOM!
このように、documentオブジェクトを使って、Webページの要素にアクセスし、その要素の内容を変更することができます。
getElementByIdメソッドやquerySelectorメソッドなどを使って、特定の要素を取得することができます。
また、DOMを操作することによって、Webページの動的な変更や、ユーザーのアクションに応じた処理を実装することができます。
DOMの操作
DOMでは、以下のような操作を行うことができます。
- 要素の取得
document.getElementById、document.querySelectorなどのメソッドを使って、HTML要素を取得することができます。
// idが"myDiv"の要素を取得する
const myDiv = document.getElementById("myDiv");
// クラス名が"myClass"の要素を取得する
const myClass = document.querySelector(".myClass");
// タグ名が"p"の要素をすべて取得する
const pTags = document.getElementsByTagName("p");
- 要素の作成・追加
document.createElementメソッドを使って、新しいHTML要素を作成し、appendChildメソッドを使って、既存の要素に子要素として追加することができます。
// 新しいp要素を作成する
const newParagraph = document.createElement("p");
// テキストを設定する
newParagraph.textContent = "This is a new paragraph.";
// idが"myDiv"の要素に新しいp要素を追加する
myDiv.appendChild(newParagraph);
- 要素の削除・置換
removeChildメソッドを使って、指定された子要素を削除することができます。
また、replaceChildメソッドを使って、指定された子要素を別の要素で置き換えることができます。
// 子要素の削除
myDiv.removeChild(newParagraph);
// 別の要素で置き換える
const newHeader = document.createElement("h1");
newHeader.textContent = "This is a new header.";
myDiv.replaceChild(newHeader, oldHeader);
- 要素の属性の変更
getAttributeメソッドを使って、要素の属性値を取得し、setAttributeメソッドを使って、要素の属性値を変更することができます。
// src属性の値を取得する
const myImage = document.getElementById("myImage");
const src = myImage.getAttribute("src");
// src属性の値を変更する
myImage.setAttribute("src", "newImage.jpg");
- イベントの追加
addEventListenerメソッドを使って、イベントリスナーを追加することができます。
例えば、ボタンをクリックした時に実行される関数を定義し、addEventListenerメソッドを使って、その関数を登録することができます。
// ボタン要素を取得する
const myButton = document.getElementById("myButton");
// クリックした時に実行される関数を定義する
function handleClick() {
console.log("Button clicked!");
}
// イベントリスナーを追加する
myButton.addEventListener("click", handleClick);
DOMのツリー構造
DOMのツリー構造は、HTMLドキュメントの構造を表し、各要素はノードと呼ばれます。DOMのノードは、次の3つの種類に分類されます。
- 要素ノード (Element Node) - HTML要素を表します。例えば、<div>、<p>、<a>など。
- テキストノード (Text Node) - HTML要素のテキストを表します。例えば、<p>Hello World!</p>のHello World!の部分。
- 属性ノード (Attribute Node) - HTML要素の属性を表します。例えば、<a href="https://www.example.com/">Example</a>のhref属性。
Discussion