Open4

JavaScript学習記録6 つみあげトレーニングブック7章

kamimura sorakamimura sora

7章_オブジェクトをさらに理解する

JavaScriptのオブジェクト

オブジェクトはプロパティの集まり

JavaScriptでは「オブジェクト」という部品を使ってプログラムを作る。
オブジェクトの特徴→構造が非常に柔軟。プロパティという変数のようなものの集まりで必要なときに好きなだけプロパティを追加できる
プロパティに関数オブジェクトを入れるとメソッドになる。使い方はほぼ同じだがオブジェクトと一体化しているためそのオブジェクトに関連する処理を行わせやすくなる。

JavaScriptでオブジェクトを定義する方法

オブジェクトの作り方(定義方法)が数種類ある。
一番簡単なオブジェクトリテラル、関数を使う方法、classキーワード
関数ベースやclassキーワードで定義したオブジェクトを利用するときはnew演算子とコンストラクタ関数を組み合わせて使う。
オブジェクトの定義を元に新しい実体を作る

kamimura sorakamimura sora

02_標準組み込みオブジェクトを利用する

標準組み込みオブジェクトとは

JavaScriptに最初から用意されているオブジェクトのことを、標準組み込みオブジェクトという

new演算子とコンストラクタでオブジェクトを作る

オブジェクトを利用するにはオブジェクトを作成する必要がある(定義済みのオブジェクトの新しい実態を作る)
オブジェクトを作るにはnew演算子とコンストラクタ関数を使う。

Dateオブジェクトを使ってみる
Dateオブジェクトは作成時に年月日時分の数値や、日付を表す文字列を渡して初期化できる。
注意が必要なのは月数のみ0から始まるルール 1月は0、12月は11になる

c7_2_1.js
let yesterday = new Date(2021, 11, 9);
let today = new Date(2021, 11, 10);
let tomorrow = new Date(2021, 11,11);

console.log(yesterday);
console.log(today);
console.log(tomorrow);

console.logメソッドでオブジェクトが記憶している日付時刻を表示している

Dateオブジェクトについて詳しく知る

DateオブジェクトはUTC(協定世界時)で1970年1月1日からの経過秒数として日付時刻を保持する
注意が必要なのは、Dateオブジェクトはプログラムを実行した地域のローカル時刻を元に作成される

c7_2_2.js
let day1 = new Date(1970, 0, 1, 0, 0, 0);
let day2 = new Date(); //引数なしでオブジェクトを作成
day2.setTime(0);       //内部のミリ秒を0に設定

console.log(day1);
console.log(day1.getTime());  //内部のミリ秒を表示
console.log(day2);
console.log(day2.getTime());  //内部のミリ秒を表示

変数day1は、日本標準時で1970年1月1日0時0分0秒をしており、内部的なミリ秒は-32,400,000(-9時間)
変数day2の方は内部的なミリ秒を0に設定したため、日本標準時は1970年1月1日9時0分0秒となっている

c7_2_2.js
let day1 = new Date(1970, 0, 1, 0, 0, 0);
let day2 = new Date(); //引数なしでオブジェクトを作成
day2.setTime(0);       //内部のミリ秒を0に設定

console.log(day1);
console.log(day1.getTime() / 1000 / 60 / 60);  
console.log(day2);
console.log(day2.getTime() / 1000 / 60 / 60);  

コンソールを使ってオブジェクトを観察する

chromeのコンソールを使って「Date」のみを入力すると↓のように表示される
                    ƒ Date() { [native code] }
斜体のfは関数オブジェクトを表しており、「Date」にはコンストラクタ関数が入っていることがわかる

「Date()」と入力してみる
'Tue Nov 12 2024 12:37:53 GMT+0900 (日本標準時)'
日付が表示されているので新しいDateオブジェクトが返されたように見えるがシングルクォートで囲まれている
返されているのは文字列であってDateオブジェクトではない

new演算子付きで入力すると新しいDateオブジェクトが返されるがダブルクォートがついていない
新しいオブジェクトが作られるのは、new演算子を付けた時だけ。

kamimura sorakamimura sora

03_プロパティとメソッドを追加する

オブジェクトにプロパティを追加する

プロパティは「.プロパティ名」に対して値を代入するだけで追加できる

c7_3_1.js
let obj = {};
obj.firstname = 'taro';
obj.lastname = 'yamada';
console.log(obj);

コンソールにはオブジェクトリテラルの定義に似た形で表示される
オブジェクトリテラルの{}内に書いても、「.プロパティ名」で追加しても同じ

オブジェクトにメソッドを追加する

メソッドはプロパティに関数オブジェクトを入れたものなのでプロパティと同じように定義できる
メソッドの定義は、アロー関数式ではなくfunction式を使用
firstnameとlastnameの内容をつなげて表示する、getFullNameメソッドを追加

c7_3_2.js
let obj2 = {};
obj2.firstname2 = 'taro';
obj2.lastname2 = 'yamada';
obj2.getFullName = function() {   //メソッドを追加
    return `${this.firstname2} ${this.lastname2}`;
}

console.log(obj2);               //オブジェクト自体を表示
console.log(obj2.getFullName());  //メソッドの戻り値を表示

getFullNameメソッドでは、同じオブジェクト内のfirstnameとlastnameを連結し、それを戻り値として返している。このとき「同じオブジェクト」を参照するために使用しているのが、thisというキーワード
thisが同じオブジェクトを参照するからfirstnameやlastnameプロパティを使用するときは
this.firstname、this.lastnameと書くことができる

オブジェクトリテラル内で全部定義する

「プロパティ.」で追加するのと、オブジェクトリテラル内で「プロパティ:値」で定義するのは同じこと
オブジェクトリテラル内でプロパティとメソッドをまとめて定義することもできる

c7_3_3.js
let obj3 = {
    firstname3: 'taro',           //プロパティを定義
    lastname3: 'yamada',
    getFullName3: function() {    //メソッドを定義
        return `${this.firstname3} ${this.lastname3}`;
    }
};

console.log(obj3);
console.log(obj3.getFullName3());

結果はc7_3_2.jsと同じだが、この書き方のほうが1つのオブジェクトをまとめて定義しているように感じる
ES2015では、拡張オブジェクトリテラルというものが導入され、オブジェクトリテラル内でメソッドを定義するときに「:function()」を省略できるようになった

c7_3_4.js
let obj4 = {
    firstname4: 'taro',           //プロパティを定義
    lastname4: 'yamada',
    getFullName4() {              //拡張オブジェクトリテラルのメソッド定義
        return `${this.firstname4} ${this.lastname4}`;
    }
};

console.log(obj4);
console.log(obj4.getFullName4());

最後の書き方が一番新しい
どれも間違いではない

存在しないメソッドを呼び出したときに起きるエラー

c7_3_2〜c7_3_4のどれかを実行した後の状態でコンソールに「obj.supername」と入力してみる
supernameは定義していないのでおかしい指示だがJavaScriptはエラーを発生させず
「undefined(未定義)」という値を返すだけ、そのまま処理を続行する。
しかし「obj.supername()」のようにメソッドとして呼び出すとエラーになる
何か名前の後に()をつけるとJavaScriptは関数かメソッドの呼び出しとみなす
「それは関数ではない」というエラーが発生する。

kamimura sorakamimura sora

04_変数のスコープを知る

名前空間

一度定義した変数は、プログラムのどこからでも呼び出せるわけではない
関数の中で作成した変数はその関数の中でしか参照することができない
次のプログラムを実行すると7行目のconsole.log(tool)の処理で変数toolが定義されていないというエラーが発生する

c7_4_1.js
let assign_tool = () => {
    let tool = '手裏剣'
}


assign_tool()
console.log(tool)

Uncaught ReferenceError: tool is not defined
at main.js:14:13
このようなエラーが出た
このエラーの原因を知るためには、JavaScriptにおける名前空間という考え方を知る方法がある
JavaScriptはさまざまなレベルの名前空間を持っている。これは変数名、関数名、クラス名などの1つの名前を持つものが1つに特定できる空間のこと。名前空間が異なれば同じ名前を持つものでも実体は別のものななる。
先ほどのプログラムでエラーが発生したのは、関数の中の名前空間はローカルな名前空間になっているから。ローカルな名前空間に作成された変数はローカル変数といい、その名前空間の中で歯科使用できない。
また関数の仮引数もローカル変数の1つなので関数の中でしか使えない。

名前空間が分かれていることの意味

varというキーワードで変数を宣言することができるが、現在ではvarで変数を宣言することは基本的には推奨されない。その理由は、letとconstは、varよりも名前空間に関する制約が厳しい。
名前空間に関する制約が厳しいことには、変数の値を更新しても、その影響が他の部分に及びにくいなどのメリットがある。そのため現在では、let,constを使うよう推奨されている。