JavaScript パターン
はじめに
JavaScript はオブジェクト指向
オブジェクト= key-value ペアのリスト
オブジェクトの種類
- ネイティブオブジェクト
- 組み込みオブジェクト(Array,Date など)
- ユーザ定義オブジェクト(const a = ;)
- ホストオブジェクト(window など)
リテラルとコンストラクタ
オブジェクトリテラル記法
a = {};
ちなみに、いわゆる「空のオブジェクト」とは、Object.prototype から継承したプロパティ・メソッドのみを持つオブジェクトのこと
組み込みコンストラクタ関数
使うな。リテラル記法を使え。
const obj = new Object();
カスタムコンストラクタ関数
new
を使うと実際には下記のような処理が行われる
const Person = function (name) {
// 暗黙的にオブジェクトを作成
// const this = Object.create(Person.prototype);
this.name = name;
// 暗黙的にオブジェクトを返す
// return this;
};
Person.prototype.say = function () {
return 'I am ' + this.name;
};
コンストラクタ内で明示的にオブジェクトをreturn
する事もできる。
この場合 、プロトタイプの継承は手動で行う必要がある。
また、暗黙的に作成されたオブジェクトは破棄される。
const Person = function (name) {
return { name: 'john' }; // Person.prototypeは継承されない
};
new を忘れたときのための保険
const Person = function () {
if (!(this instanceof Person)) {
return new Person();
}
// ...something...
};
配列リテラル
配列リテラルを使え。配列コンストラクタは使うな。
正規表現リテラル
正規表現リテラルを使え。正規表現コンストラクタは使うな。
プリミティブのラッパー
string, number, boolean にはラッパが存在する。プリミティブは、即時にオブジェクトととして振る舞えるので、明示的にラッパを使う機会は、ほぼない。
'abc'.toUpperCase();
(22 / 7).toPrecision(3);
使う必要があるのは、引数をプリミティブに変換したいときだけ。
const num = Number('3');
const str = String(3);
エラーオブジェクト
Error()
,SyntaxError()
,TypeError()
など、組み込みのエラーコンストラクタが存在する。- これらは、
throw
とともに使用される。 - 作成されるオブジェクトは必ず
name
とmessage
のプロパティを持っている。それ以外のプロパティはブラウザ拡張のため、存在は信頼できない。 throw
には独自のオブジェクトとを指定することもできる。
throw new Error('some message'); // newはなくても動作は同じ
throw {
name: 'MyError',
message: 'something bad happend',
};
関数
- 関数とは、実行可能なオブジェクトのことである。
- 関数はローカルスコープを提供する
Expression と Statement
関数の作成には 3 種類の方法がある。
// named function expression(名前付き関数式)
const add = function add() {};
// anonymous function expression(無名関数式)
const add = function () {};
// function statement(関数宣言)
function add() {}
使い分け
- Expression
- 変数やプロパティに代入したいとき
- 引数として渡したいとき
- Statement
- その他の場合
- Statement は必ずプログラムコード(関数本体の中もしくはグローバル空間)にのみ存在する
Named Function Expression と Function Statement の違い
- Expression は変数の宣言のみ巻き上げられる(undefined)
- Statement はファンクションの定義も巻き上げられる
a(); // => ok
b(); // => errorになる。b===undefined だから。
function a() {}
const b = function () {};
name プロパティ
function foo(); // foo.name === 'foo'
const baz = function baz2(){}; // baz.name === 'baz2'
const bar = function(){}; // bar.name === 'bar'
named function にしておくと、デバッグ時にファンクション名が表示されるので便利。