はじめに
Effective JavaScript を読み返していると、項目 31 で覚えておくべき事項として以下が紹介されていました。
非標準の __proto__ プロパティよりも、標準に準拠した Object.getPrototypeOf が好ましい。
なるほど Object.getPrototypeOf() があるのか
ここで「Object.getPrototypeOf()
は obj.constructor.prototype
では代用できないだろうか」という疑問が湧きました。そこで調べてみると、StackOverflow に is Object.getPrototypeOf() same as Object.constructor.prototype in Javascript? というまさしく求めていた記事を発見しました。そこで、その記事の内容を整理して共有したいと思います。
追記 (2016/11/16 (水))
__proto__ プロパティは標準化されていると @mysticatea 様にご指摘頂きました。ありがとうございます
確かに MDN の Object.prototype.__proto__ にも
__proto__ プロパティはECMAScript第6版言語仕様で標準化されました。そして、将来にサポートされます。
と言及されていますね。ただし、パフォーマンス上の観点から、やはり使用は推奨されていないようです。
概要
先にタイトルの答えを発表すると NO です。
例えば Object.create() で引数に null
を渡してオブジェクトを生成したとします。これは prototype
を null
としてオブジェクトを生成するということです。この場合 obj.constructor
は undefined
となるため obj.constructor.prototype
を取得することはできません。
let obj1 = Object.create(null);
obj1.constructor; // undefined
一方 Object.getPrototypeOf()
メソッドは null
を返します。
Object.getPrototypeOf(obj1); // null
prototype
が null
の場合でも利用できるのは便利ですね。
対して、一般的なオブジェクト (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)
で生成したオブジェクトについても、手動で prototype
に Object.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のコンストラクタを指しているとは限りません。
とのご指摘を頂きました。ありがとうございます
確かに、このことも 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