質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.43%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

460閲覧

Object.getPrototypeOf(obj) と obj.__proto__ の違いを教えてください

Lhankor_Mhy

総合スコア36342

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1グッド

3クリップ

投稿2023/10/27 08:04

編集2023/11/02 09:03

前提

指定されたオブジェクトのプロトタイプ (つまり、内部プロパティ [[Prototype]] の値) を返します。
Object.getPrototypeOf() - JavaScript | MDN

アクセスされるオブジェクトの内部の [[Prototype]] (オブジェクトまたは null のどちらか) を暴露します。
Object.prototype.__proto__ - JavaScript | MDN

とMDNにあるため、同じものを返すのだろうと思っていましたが、これらが違うものを返すケースがありました。

発生している問題・エラーメッセージ

Object.setPrototypeOfを使ったりobj.__proto__.__proto__に代入するなどして、[[Prototype]][[Prototype]]nullに変更する(削除する?)と、Object.getPrototypeOf(obj)obj.__proto__が一致しません。
(おそらく、下記コードを見ていただいた方が早いです)

これについて、両者の違いを教えてください。

該当のソースコード

js

1{ 2 class Grandma { 3 4 } 5 6 class Mama extends Grandma { 7 8 } 9 10 const child = new Mama(); 11 12 console.log(child.__proto__ === Object.getPrototypeOf(child)) // true 13 console.log(child.__proto__.__proto__ === Object.getPrototypeOf(Object.getPrototypeOf(child))) // true 14 15 Object.setPrototypeOf(Object.getPrototypeOf(child), null) // null の場合は、__proto__ と Object.getPrototypeOf() が一致しない。 16 // child.__proto__.__proto__ = null // 同上 17 18 console.log(child.__proto__) // undefined 19 console.log(Object.getPrototypeOf(child) === Mama.prototype) // true 20 console.log(child.__proto__ === Object.getPrototypeOf(child)) // false 21} 22 23{ 24 class Grandma { 25 26 } 27 28 class Mama extends Grandma { 29 30 } 31 32 const child = new Mama(); 33 34 console.log(child.__proto__ === Object.getPrototypeOf(child)) // true 35 console.log(child.__proto__.__proto__ === Object.getPrototypeOf(Object.getPrototypeOf(child))) // true 36 37 Object.setPrototypeOf(Object.getPrototypeOf(child), {}) // 空のオブジェクトなどの場合は、__proto__ と Object.getPrototypeOf() が一致する。 38 // child.__proto__.__proto__ = {} // 同上 39 40 console.log(child.__proto__) // === Mama.prototype 41 console.log(Object.getPrototypeOf(child) === Mama.prototype) // true 42 console.log(child.__proto__ === Object.getPrototypeOf(child)) // true 43}

補足情報(FW/ツールのバージョンなど)

Object.prototype.__proto__が非推奨であることは理解していますので、「そもそもObject.prototype.__proto__を使っているのが間違い」という回答は、当方が望んでいるものではありませんのでご理解ください。


解決後の追記

解決後に以下のようにしてObject.prototype.__proto__のゲッターを直接参照して試したところ、動作しましたので、やはりプロトタイプチェーンが切れていることが原因だとわかりました。

js

1Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get.bind(child)()
arcxor👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2023/10/27 08:27 編集

コメントありがとうございます。MDN のリンクから以下のページについては参照いたしました。 https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.prototype.__proto__ https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.getprototypeof 管見の限り、同じことをしているように読めました。ここから違いが読み取れるのであれば、教えていただけると助かります。
maisumakun

2023/10/27 08:27

たしかに、仕様書上の違いはないですね……
guest

回答1

0

ベストアンサー

プロトタイプチェーン(prototype chain)

Stackoverflowに同じ趣旨の質問がありました。
https://stackoverflow.com/questions/35458183/why-is-proto-undefined-for-object-createnull

回答で引用されている主要箇所を引用します。
https://bugs.chromium.org/p/chromium/issues/detail?id=506166

This is working as specified. ES6 __proto__ is a getter defined on Object.prototype. For an object that doesn't have that in its prototype chain it is not accessible (just like, say, hasOwnProperty isn't). You need to use Object.getPrototypeOf instead.

コード

__proto__ プロパティと Object.getPrototypeOf() の比較コード。

javascript

1const obj = new Object; 2obj.__proto__ = null; 3console.log(obj.__proto__); // undefined 4console.log(Object.getPrototypeOf(obj)); // null
  • __proto__ プロパティをプロトタイプチェーンで探索する場合、[[Prototype]]null であるなら、探索を中止し、undefined 値を返します。
  • Object.getPrototypeOf() は、[[Prototype]] の値をそのまま返します(プロトタイプチェーンの影響を受けません)。

[[Prototype]] の正確な値を取得したい場合は Object.getPrototypeOf() を使うのが妥当といえそうです。

投稿2023/10/28 01:49

編集2023/10/28 01:51
think49

総合スコア18172

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2023/10/28 02:00

ご回答ありがとうございます。 あー、なるほど…… プロトタイプをぶった切ってしまったので、プロトタイプチェーンをたどってネイティブな実装のところまでたどり着けないんですね。 よくわかりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.43%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問