Membuat objek JS dengan Object.create (null)?

150

Saya tahu banyak cara untuk membuat objek JS tapi saya tidak tahu Object.create(null)itu.

Pertanyaan:

apakah persis sama dengan:

var p = {}

vs.

var p2 = Object.create(null);

?

Royi Namir
sumber

Jawaban:

199

Mereka tidak setara. {}.constructor.prototype == Object.prototypesementara Object.create(null)tidak mewarisi dari apa pun dan dengan demikian tidak memiliki sifat sama sekali.

Dengan kata lain: Sebuah javascript objek mewarisi dari Object secara default, kecuali Anda secara eksplisit membuat dengan null sebagai prototipe, seperti: Object.create(null).

{}sebaliknya akan setara dengan Object.create(Object.prototype).


Di Chrome Devtool Anda dapat melihat bahwa Object.create(null)tidak memiliki __proto__properti, sementara itu {}tidak.

masukkan deskripsi gambar di sini

Peter Herdenborg
sumber
99

Mereka jelas tidak setara. Saya menulis jawaban ini untuk lebih menjelaskan mengapa itu membuat perbedaan.

  1. var p = {};

    Menciptakan objek yang mewarisi properti dan metode dari Object.

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

    Membuat objek yang tidak mewarisi apa pun.

Jika Anda menggunakan objek sebagai peta, dan Anda membuat objek menggunakan metode 1 di atas, maka Anda harus ekstra hati-hati saat melakukan pencarian di peta. Karena properti dan metode dari Objectdiwarisi, kode Anda mungkin mengalami kasus di mana ada kunci di peta yang tidak pernah Anda masukkan. Misalnya, jika Anda melakukan pencarian toString, Anda akan menemukan fungsi, meskipun Anda tidak pernah memberikan nilai itu di sana. Anda dapat menyiasatinya seperti ini:

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

Perhatikan bahwa tidak apa-apa untuk menetapkan sesuatu p.toString, itu hanya akan menimpa toStringfungsi warisan p.

Perhatikan bahwa Anda tidak bisa melakukan begitu saja p.hasOwnProperty('toString')karena Anda mungkin telah memasukkan kunci "hasOwnProperty" ke dalam p, jadi kami memaksanya untuk menggunakan implementasi di Object.

Di sisi lain, jika Anda menggunakan metode 2 di atas, maka Anda tidak perlu khawatir tentang hal-hal yang Objectmuncul di peta.

Anda tidak dapat memeriksa keberadaan properti dengan yang sederhana ifseperti ini:

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

Nilai mungkin berupa string kosong, mungkin false, atau null, atau undefined, atau 0, atau NaN, dll. Untuk memeriksa apakah suatu properti ada, Anda masih perlu menggunakan Object.prototype.hasOwnProperty.call(p, someKey).

doug65536
sumber
6
Alternatif yang lebih sederhana untuk memeriksa keberadaan properti adalah:if (someKey in p) {
mrcrowl
2
@ mrcrowl Hanya jika digunakan Object.create(null). Saya lebih suka untuk tidak membuat asumsi seperti itu, bahkan jika Anda benar bahwa itu digunakan Object.create(null), kode dapat berubah, objek dapat diganti dengan yang mewarisi Objectdi beberapa titik. hasOwnPropertyselalu berhasil.
doug65536
1
Saya merasa berhati-hati tentang sesuatu seperti ini seharusnya tidak perlu. Saya menghargai jawaban Anda tetapi dokumentasi harus memberi Anda api yang diperlukan untuk bekerja dengan kode apa pun yang Anda kerjakan Jika Anda mengambil beberapa kode acak dari github, maka Anda dapat menggunakannya dan aman dari pembaruan yang kurang terdokumentasi. Belum lagi {}jauh lebih lazim daripada Object.create(null), bahwa jika kode Anda secara tidak sengaja mengambil properti yang diwarisi pada saat ini, Anda mungkin memiliki bug yang jauh lebih besar untuk dikhawatirkan. Saya hanya dapat melihat orang menggunakan Object.create (null) sebagai optimasi kecil.
aaaaaa
Negasi ganda !!p[key]bekerja dengan baik Object.create(null). Tapi hasKey = (key, input) => Object.prototype.hasOwnProperty.call(input, key)tidak buruk baik
andreid
> Perhatikan bahwa Anda tidak bisa hanya melakukan p.hasOwnProperty ('toString') karena Anda mungkin telah memasukkan kunci "hasOwnProperty" ke p, jadi kami memaksanya untuk menggunakan implementasi di Object. Itu tidak perlu. Dalam hal ini, Anda tidak dapat menggunakan metode apa pun pkarena setiap metode dapat dimasukkan dan menjadi tidak aman.
xianshenglu
1

Membuat objek dengan menggunakan {}akan membuat objek dengan prototipe Object.prototypeyang mewarisi fungsi dasar dari Objectprototipe sementara membuat objek dengan menggunakan Object.create(null)akan membuat objek kosong yang prototipenya nol.

Praveen Kishor
sumber
0

Jika seseorang mencari implementasi Object.create(null), hanya untuk mengetahui cara kerjanya. Itu ditulis menggunakan __proto__yang non-standar dan karenanya, saya tidak merekomendasikannya .

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;
}

Catatan : Saya menulis ini, karena penasaran, dan hanya ditulis dalam istilah sederhana, misalnya, saya tidak mentransfer deskriptor properti dari objek kedua ke objek kembali.

Aravind
sumber
1
Perhatikan bahwa pada rilis ECMAScript di musim panas, __proto__sekarang akan secara resmi menjadi bagian dari bahasa tersebut.
Chiru
1
Kenapa -1masuk arguments.length>0?arguments[0]:-1;?
happy_marmoset
@happy_marmoset keterlambatan respons, tetapi sepertinya itu hanya pengganti non-nol sehingga Objectprototipe dipertahankan jika argumen pertama tidak diberikan. Nama variabel bisa jauh lebih baik di sini.
Mike Hill
Juga, parameter kedua harus menggambarkan deskriptor properti daripada properti aktual itu sendiri. Lihat referensi di sini: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Mike Hill
0

Ketika Anda membuat Obyek dengan Object.create (null) itu berarti Anda membuat Obyek tanpa prototipe. null di sini berarti akhir dari rantai prototipe. Namun demikian ketika Anda membuat objek seperti {} objek prototipe akan ditambahkan. Karenanya ini adalah dua objek yang berbeda, satu dengan prototipe yang lain tanpa prototipe. Semoga ini bisa membantu

pengguna13624607
sumber