概要
JavaScriptを学習、理解を深めるため「JavaScript Primer 迷わないための入門書」を読み、
理解した内容等を記載していく。
「【JavaScript】JavaScript入門一覧」に他の記事をまとめています。
この記事で理解できること
- プロトタイプオブジェクト(Object.prototypeプロパティで定義されたオブジェクト)とは
- Objectの継承
- プロトタイプメソッドとインスタンスメソッドの優先度
Objectはすべての元
-
Object(クラス)
は、全てのオブジェクトの元である。 -
Array
オブジェクトやString
オブジェクトなどは、このObject
を継承している。*1
*1 「ArrayオブジェクトやStringオブジェクトなどは、このObjectを継承している。」とは、
正確にはObject.prototypeプロパティで定義された、prototype
オブジェクトを継承している。
(Array、Stringオブジェクトなどを子
と捉えた場合、Objectが親
のような存在)
「定義していないメソッドが使える。 なぜ?」
下記、例のように、あるオブジェクトを作成し、自ら定義していないtoStringメソッド
を呼び出してみる。
すると、定義していないはずなのに、呼び出し・処理
が正しく実行される。
メモ:toStringメソッドは、オブジェクトを表す文字列を返すメソッド
MDN『Object.prototype.toString()』
// 数値を値として持つプロパティnumのみを定義したオブジェクトを作成
const obj = { num: 123 };
// numプロパティの値の型を調べる
console.log(typeof obj.num); // => number
// numプロパティの値をtoStringメソッドで文字列に変換し、型を調べる
console.log(typeof obj.num.toString()); // => string
この自ら定義していないtoStringメソッド
が使用できる理由として、
- オブジェクト(今回の例では作成した
obj
)の継承元であるObject(prototypeオブジェクト)
で定義されているからである。 - また、その結果、あるオブジェクトを
作成した時点
でObjectを継承している(Objectはすべての元)ということも分かる。
(Object.prototype)prototypeオブジェクト
-
Object.prototype
プロパティに定義された、全てのオブジェクト作成時に自動的に追加される
特殊なオブジェクト。 -
prototype
オブジェクトに組み込まれているメソッドはプロトタイプメソッド
と呼ばれる。 - Objectを継承した任意のオブジェクトから
プロトタイプメソッド
が参照できる仕組みをプロトタイプチェーン
と呼ぶ。
// prototypeプロパティを確認してみる
console.dir(Object.prototype)
// => constructor: ƒ Object()
// => propertyIsEnumerable: ƒ propertyIsEnumerable()
// => toString: ƒ toString() ★★先ほど使用したtoStringメソッドも存在する★★
// ...etc
プロトタイプメソッドとインスタンスメソッドの優先度
- プロトタイプメソッドと
同名のメソッドが定義されている場合
、インスタンス(が持つ)メソッドの呼び出しが優先される。
(ここでの「インスタンス」は、下記例で作成しているオブジェクト「instance1」「instance2」を指す)
const instance1 = {
name: "instance1"
}
const instance2 = {
name: "instance2",
// プロトタイプメソッドと同名のメソッドをオブジェクトで定義(インスタンスメソッド)
toString: () => {
return "インスタンスメソッド";
}
}
// toStringメソッドを持っているか確認するための関数を別途定義
function hasToString(obj) {
if (typeof obj.toString()) {
return `${obj.name}にtoStringは存在します`;
} else {
return "toStringは存在しません";
}
}
// 各オブジェクトはtoStringメソッドを持っている
console.log(hasToString(instance1)); // => instance1にtoStringは存在します
console.log(hasToString(instance2)); // => instance2にtoStringは存在します
// じゃあtoStringメソッドを実行してみよう
console.log(instance1.toString()); // => [object Object]
console.log(instance2.toString()); // => インスタンスメソッド(※インスタンスメソッドが優先されている)
(参考)Object.prototypeを継承しないオブジェクト
-
Object.create(null)
でオブジェクトを作成すると、
プロパティやメソッドを持たない(Object.prototypeを継承しない)空のオブジェクトを作成できる。
ES2015
から追加されたMapオブジェクト
の代わりとして利用されていたようです。
const obj = Object.create(null);
if (typeof obj.toString()) {
console.log("toStringが存在します");
}
// => TypeError: obj.toString is not a function(存在していない!!)