Object.create(null)でJSオブジェクトを作成しますか?


150

私はJSオブジェクトを作成する方法をたくさん知っていますが、の方法を知りませんでしたObject.create(null)

質問:

それはまったく同じですか:

var p = {}

var p2 = Object.create(null);

回答:


199

それらは同等ではありません。{}.constructor.prototype == Object.prototype一方Object.create(null)、何も継承しないため、プロパティはまったくありません。

つまり、次のように、プロトタイプとしてnullを明示的に作成しない限り、JavaScriptオブジェクトはデフォルトでObjectを継承します。 Object.create(null)

{}代わりにと同等になりObject.create(Object.prototype)ます。


Chrome Devtool Object.create(null)では、__proto__プロパティはあり{}ませんが、プロパティがあることがわかります。

ここに画像の説明を入力してください


99

それらは明らかに同等ではありません。私はこの答えを書いて、なぜそれが違いを生むのかをより完全に説明します。

  1. var p = {};

    からプロパティとメソッドを継承するオブジェクトを作成しますObject

  2. var p2 = Object.create(null);

    何も継承しないオブジェクトを作成します。

オブジェクトをマップとして使用していて、上記の方法1を使用してオブジェクトを作成する場合、マップでルックアップを行うときは特に注意する必要があります。のプロパティとメソッドObjectが継承されるため、コードにマップ内に挿入したことのないキーがある場合があります。たとえば、でルックアップを行った場合toString、その値をそこに配置していなくても、関数が見つかります。あなたはこのようにそれを回避することができます:

if (Object.prototype.hasOwnProperty.call(p, 'toString')) {
    // we actually inserted a 'toString' key into p
}

に何かを割り当てても問題ないことに注意してください。これはp.toString、継承されたtoString関数を単にオーバーライドするだけpです。

p.hasOwnProperty('toString')「hasOwnProperty」というキーをに挿入した可能性があるため、単に実行することはできませんp。したがって、Objectます。

一方、上記の方法2を使用する場合は、次のことについて心配する必要はありません。 Objectは、マップに表示さ。

次のifような単純な方法では、プロパティの存在を確認できません。

// Unreliable:
if (p[someKey]) {
    // ...
}

値は空の文字列の場合もあればfalse、or null、or undefined、or 0、or NaN、or などの場合もありますObject.prototype.hasOwnProperty.call(p, someKey)。プロパティが存在するかどうかを確認するには、引き続きを使用する必要があります。


6
プロパティの有無をチェックするためのシンプルな選択肢がある:if (someKey in p) {
mrcrowl

2
@mrcrowl彼らが使用しObject.create(null)た場合のみ。私はそのような仮定をしないことを好みます。たとえそれが使用されたことが完全に正しいとしてもObject.create(null)、コードは変更される可能性があり、オブジェクトはObjectある時点で継承するものに置き換えられる可能性があります。hasOwnProperty常に動作します。
doug65536

1
このようなことに気を付ける必要はないはずです。私はあなたの答えに感謝しますが、ドキュメントはあなたが働いているどんなコードででも働くのに必要なAPIをあなたに与えるでしょう githubからランダムなコードを取得している場合は、それをフォークして、文書化されていない更新から安全にすることができます。言うまでもないことですが、コードがこの時点で誤って継承されたプロパティを取得した場合{}Object.create(null)、さらに大きなバグが発生する可能性があります。マイナーな最適化としてObject.create(null)を使用している人しか見ることができません。
aaaaaa

二重否定!!p[key]はでう​​まく機能しObject.create(null)ます。しかしhasKey = (key, input) => Object.prototype.hasOwnProperty.call(input, key)、悪くはありません
andreid

>「hasOwnProperty」というキーをpに挿入した可能性があるため、p.hasOwnProperty( 'toString')だけを実行することはできないため、Objectの実装を使用するように強制します。それは不要です。この場合、pすべてのメソッドが挿入されて安全でなくなる可能性があるため、でメソッドを使用することはできません。
xianshenglu 2018

1

を使用{}してオブジェクトを作成すると、プロトタイプObject.prototypeから基本関数を継承するObjectプロトタイプのオブジェクトObject.create(null)が作成されます。使用してオブジェクトを作成すると、プロトタイプがnullの空のオブジェクトが作成されます。


0

誰かがの実装を探している場合はObject.create(null)、それがどのように機能するかを知るだけです。これは__proto__非標準で使用されているため、お勧めしません

function objectCreateMimic()
{
  /*optional parameters: prototype_object, own_properties*/
  var P = arguments.length>0?arguments[0]:-1;
  var Q = arguments.length>1?arguments[1]:null;
  var o = {};
  if(P!==null && typeof P === "object")
  {
    o.__proto__ = P;
  }
  else if(P===null)
  {
    o.__proto__ = null;
  }
  if(Q!==null && typeof Q === "object")
  {
   for(var key in Q)
   {
     o[key] = Q[key];
   }
  }
  return o;
}

:私はこれを好奇心から書きましたが、簡単な言葉でしか書かれていません。たとえば、プロパティ記述子を2番目のオブジェクトから戻りオブジェクトに転送していません。


1
なお、夏にはECMAScriptのリリースのように、__proto__今になる正式言語の一部です。
Chiru

1
なぜ -1arguments.length>0?arguments[0]:-1;
happy_marmoset

@happy_marmoset遅い応答ですが、それはnull以外のプレースホルダーのように見えるので、 Object、最初の引数が指定されていない場合にプロトタイプが保持されるように、。変数名はここではずっと良いかもしれません。
マイク・ヒル

また、2番目のパラメータはプロパティを説明する必要があります 、実際のプロパティ自体ではなく記述子を記述。ここでリファレンスを参照してください:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
マイク・ヒル

0

Object.create(null)でオブジェクトを作成すると、プロトタイプなしでオブジェクトが作成されることになります。ここでnullは、プロトタイプチェーンの終わりを意味します。それでも、{}のようなオブジェクトを作成すると、オブジェクトプロトタイプが追加されます。したがって、これらは2つの異なるオブジェクトであり、1つはプロトタイプあり、もう1つはプロトタイプなしです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.