0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【JavaScript】プロトタイプオブジェクト

Posted at

概要

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(存在していない!!)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?