Object.getPrototypeOf(obj) は obj.constructor.prototype と同義か?

More than 1 year has passed since last update.


はじめに

Effective JavaScript を読み返していると、項目 31 で覚えておくべき事項として以下が紹介されていました。


非標準の __proto__ プロパティよりも、標準に準拠した Object.getPrototypeOf が好ましい。


なるほど Object.getPrototypeOf() があるのか :innocent:

ここで「Object.getPrototypeOf()obj.constructor.prototype では代用できないだろうか」という疑問が湧きました。そこで調べてみると、StackOverflow に is Object.getPrototypeOf() same as Object.constructor.prototype in Javascript? というまさしく求めていた記事を発見しました。そこで、その記事の内容を整理して共有したいと思います。


追記 (2016/11/16 (水))

__proto__ プロパティは標準化されていると @mysticatea 様にご指摘頂きました。ありがとうございます :bow:

確かに MDN の Object.prototype.__proto__ にも


__proto__ プロパティはECMAScript第6版言語仕様で標準化されました。そして、将来にサポートされます。


と言及されていますね。ただし、パフォーマンス上の観点から、やはり使用は推奨されていないようです。


概要

先にタイトルの答えを発表すると NO :no_good: です。

例えば Object.create() で引数に null を渡してオブジェクトを生成したとします。これは prototypenull としてオブジェクトを生成するということです。この場合 obj.constructorundefined となるため obj.constructor.prototype を取得することはできません。

let obj1 = Object.create(null);

obj1.constructor; // undefined

一方 Object.getPrototypeOf() メソッドは null を返します。

Object.getPrototypeOf(obj1); // null

prototypenull の場合でも利用できるのは便利ですね。

対して、一般的なオブジェクト (prototype として Object.prototype を持つオブジェクト) の場合は一致します。

let obj2 = {};

Object.getPrototypeOf(obj2); // Object.prototype
obj.constructor.prototype; // Object.prototype

Object.getPrototypeOf(obj2) === obj.constructor.prototype; // true

なお Object.create(null) で生成したオブジェクトについても、手動で prototypeObject.prototype 設定すれば、一般的なオブジェクトの場合と同じ挙動になります。

let obj3 = Object.create(null);

Object.setPrototypeOf(obj3, Object.prototype);

obj3.constructor.prototype; // Object.prototype
Object.getPrototypeOf(obj3); // Object.prototype

obj3.constructor.prototype === Object.getPrototypeOf(obj3); // true

なお Object.setPrototypeOf() は ECMAScript 6 のメソッドです。


追記 (2016/11/16 (水))

@mysticatea 様より


obj.constructorは書き換え可能なプロパティであるため、本当にobjのコンストラクタを指しているとは限りません。


とのご指摘を頂きました。ありがとうございます :bow:

確かに、このことも Object.getPrototypeOf(obj)obj.constructor.prototype の大きな差異ですね。

function PseudoObject() {};

PseudoObject.prototype = {};

let obj4 = new PseudoObject();

obj4.constructor.prototype; // Object.prototype
Object.getPrototypeOf(obj4); // PseudoObject.prototype

obj4.constructor.prototype === Object.getPrototypeOf(obj4); // false


参考