Saya baru-baru ini menemukan Object.create()
metode dalam JavaScript, dan saya mencoba untuk menyimpulkan bagaimana hal itu berbeda dari membuat contoh objek baru new SomeFunction()
, dan ketika Anda ingin menggunakan satu di atas yang lain.
Perhatikan contoh berikut:
var test = {
val: 1,
func: function() {
return this.val;
}
};
var testA = Object.create(test);
testA.val = 2;
console.log(test.func()); // 1
console.log(testA.func()); // 2
console.log('other test');
var otherTest = function() {
this.val = 1;
this.func = function() {
return this.val;
};
};
var otherTestA = new otherTest();
var otherTestB = new otherTest();
otherTestB.val = 2;
console.log(otherTestA.val); // 1
console.log(otherTestB.val); // 2
console.log(otherTestA.func()); // 1
console.log(otherTestB.func()); // 2
Perhatikan bahwa perilaku yang sama diamati dalam kedua kasus. Bagi saya, perbedaan utama antara kedua skenario ini adalah:
- Objek yang digunakan
Object.create()
sebenarnya membentuk prototipe dari objek baru, sedangkan dalamnew Function()
dari properti / fungsi yang dinyatakan tidak membentuk prototipe. - Anda tidak dapat membuat penutupan dengan
Object.create()
sintaks seperti yang Anda lakukan dengan sintaks fungsional. Ini logis mengingat lingkup tipe leksikal (vs blok) dari JavaScript.
Apakah pernyataan di atas benar? Dan apakah saya kehilangan sesuatu? Kapan Anda akan menggunakan satu di atas yang lain?
EDIT: tautan ke versi jsfiddle dari contoh kode di atas: http://jsfiddle.net/rZfYL/
Jawaban:
Ya,
Object.create
membangun objek yang mewarisi langsung dari yang diteruskan sebagai argumen pertama.Dengan fungsi konstruktor, objek yang baru dibuat mewarisi dari prototipe konstruktor, misalnya:
Dalam contoh di atas,
o
mewarisi langsung dariSomeConstructor.prototype
.Ada perbedaan di sini, dengan
Object.create
Anda dapat membuat objek yang tidak mewarisi dari apa punObject.create(null);
,, di sisi lain, jika Anda mengatur objekSomeConstructor.prototype = null;
yang baru dibuat akan diwarisi dariObject.prototype
.Nah, Anda bisa membuat penutupan, misalnya menggunakan argumen deskriptor properti:
Perhatikan bahwa saya sedang berbicara tentang metode ECMAScript Edisi 5
Object.create
, bukan shim Crockford.Metode ini mulai diterapkan secara native di browser terbaru, periksa tabel kompatibilitas ini .
sumber
foo;
diselesaikan dalam lingkungan leksikal saat ini . 2) Untuk memberikan cara yang mudah untuk mengimplementasikan warisan, ini adalah konstruksi yang sangat kuat. IMO Saya akan menggunakannya karena sangat sederhana dan ringan, tetapi untuk kode produksi, kita masih perlu menunggu beberapa saat sampai ES5 didukung secara luas. Tentang fitur yang hilang, fakta membuat objek "asli",Object.create(null);
hilang, sangat berguna untuk mengimplementasikan objek seperti tabel hash yang dapat diandalkan ...Object.create(null)
berarti Anda tidak perlu menggunakanhasOwnProperty()
omong kosong saat iterasi karena tidak mewarisi ??? Saya suka itu - terima kasih. Tentu saja, semua orang masih akan melakukannyahasOwnProperty
karena tidak semua orang akan menggunakanObject.create(null)
jadi saya tidak yakin itu manfaat nyata ... Sejauh ini saya telah menemukan "manfaat" lain yangObject.create()
sama sekali tidak meyakinkan.Sangat sederhana dikatakan,
new X
adalahObject.create(X.prototype)
dengan tambahan menjalankanconstructor
fungsi. (Dan membericonstructor
kesempatanreturn
pada objek aktual yang seharusnya menjadi hasil dari ekspresi alih-alihthis
.)Itu dia. :)
Jawaban sisanya hanya membingungkan, karena ternyata tidak ada orang lain yang membaca definisi
new
keduanya. ;)sumber
Berikut adalah langkah-langkah yang terjadi secara internal untuk kedua panggilan:
(Petunjuk: satu-satunya perbedaan dalam langkah 3)
new Test()
:new Object()
objobj.__proto__
keTest.prototype
return Test.call(obj) || obj; // normally obj is returned but constructors in JS can return a value
Object.create( Test.prototype )
new Object()
objobj.__proto__
keTest.prototype
return obj;
Jadi pada dasarnya
Object.create
tidak menjalankan konstruktor.sumber
new
pada dasarnya semua fungsi digandakan, sementaraObject.create
tidak.Biarkan saya mencoba menjelaskan (lebih banyak di Blog ):
Car
konstruktorvar Car = function(){}
, ini adalah bagaimana hal-hal yang internal: Kami memiliki satu{prototype}
link yang tersembunyi untukFunction.prototype
yang tidak dapat diakses dan satuprototype
linkCar.prototype
yang dapat diakses dan memiliki aktualconstructor
dariCar
. Function.prototype dan Car.prototype memiliki tautan tersembunyiObject.prototype
.Ketika kita ingin membuat dua objek yang setara dengan menggunakan
new
operator dancreate
metode maka kita harus melakukannya seperti ini:Honda = new Car();
danMaruti = Object.create(Car.prototype)
. Apa yang terjadi?Honda = new Car();
- Ketika Anda membuat objek seperti ini, maka{prototype}
properti tersembunyi diarahkan keCar.prototype
. Jadi di sini,{prototype}
objek Honda akan selaluCar.prototype
- kita tidak punya pilihan untuk mengubah{prototype}
properti objek. Bagaimana jika saya ingin mengubah prototipe dari objek kami yang baru dibuat?Maruti = Object.create(Car.prototype)
- Ketika Anda membuat objek seperti ini, Anda memiliki opsi tambahan untuk memilih{prototype}
properti objek Anda . Jika Anda ingin Car.prototype sebagai yang{prototype}
lalu kirimkan sebagai parameter dalam fungsi. Jika Anda tidak ingin ada{prototype}
untuk objek Anda maka Anda dapat melewatinull
seperti ini:Maruti = Object.create(null)
.Kesimpulan - Dengan menggunakan metode ini
Object.create
Anda memiliki kebebasan untuk memilih{prototype}
properti objek Anda . Dinew Car();
, Anda tidak memiliki kebebasan itu.Cara yang disukai dalam OO JavaScript:
Misalkan kita memiliki dua objek
a
danb
.Sekarang, misalkan
a
memiliki beberapa metode yangb
juga ingin diakses. Untuk itu, kita memerlukan pewarisan objek (a
harus menjadi prototipeb
hanya jika kita ingin akses ke metode tersebut). Jika kami memeriksa prototipea
danb
kemudian kami akan menemukan bahwa mereka berbagi prototipeObject.prototype
.Masalah - kami ingin objek
a
sebagai prototipeb
, tetapi di sini kami membuat objekb
dengan prototipeObject.prototype
. Solusi - ECMAScript 5 diperkenalkanObject.create()
, untuk mencapai warisan dengan mudah. Jika kita membuat objekb
seperti ini:kemudian,
Jadi, jika Anda melakukan scripting berorientasi objek maka
Object.create()
sangat berguna untuk warisan.sumber
a.isPrototypeOf(b);
akan mengembalikanfalse
yang benar, karena kedua Objek berbeda dan menunjuk ke memori yang berbeda. Cara yang benar untuk melakukan ini dengannew
operator ada di sini. - jsfiddle.net/167ununp .Ini:
dan
sangat mirip. Satu perbedaan penting adalah bahwa
new Foo
sebenarnya menjalankan kode konstruktor, sedangkanObject.create
tidak akan menjalankan kode sepertiPerhatikan bahwa jika Anda menggunakan versi dua-parameter
Object.create()
maka Anda dapat melakukan banyak hal yang lebih kuat.sumber
Object.create
dalam bentuk yang paling sederhana seperti ini memungkinkan Anda untuk menghilangkan fungsi konstruktor dari kode Anda sambil mengambil keuntungan dari warisan prototipe.Perbedaannya adalah apa yang disebut "warisan pseudoklasik vs purwarupa". Sarannya adalah untuk menggunakan hanya satu jenis dalam kode Anda, bukan mencampur keduanya.
Dalam warisan pseudoklasik (dengan operator "baru"), bayangkan bahwa Anda pertama-tama mendefinisikan kelas pseudo, dan kemudian membuat objek dari kelas itu. Misalnya, tentukan "Orang" kelas pseudo, lalu buat "Alice" dan "Bob" dari "Orang".
Dalam warisan prototypal (menggunakan Object.create), Anda secara langsung membuat orang tertentu "Alice", dan kemudian membuat orang lain "Bob" menggunakan "Alice" sebagai prototipe. Tidak ada "kelas" di sini; semua benda.
Secara internal, JavaScript menggunakan "pewarisan prototypal"; cara "pseudoklasik" hanyalah gula.
Lihat tautan ini untuk perbandingan dua cara.
sumber
Ringkasan:
1) dengan
new
kata kunci ada dua hal yang perlu diperhatikan;a) fungsi digunakan sebagai konstruktor
b)
function.prototype
objek diteruskan ke__proto__
properti ... atau di mana__proto__
tidak didukung, itu adalah tempat kedua di mana objek baru terlihat untuk menemukan properti2) dengan
Object.create(obj.prototype)
Anda membangun objek (obj.prototype
) dan meneruskannya ke objek yang dimaksud .. dengan perbedaan bahwa sekarang objek baru__proto__
juga menunjuk ke obj.prototype (harap ref oleh xj9 untuk itu)sumber
Varian pembuatan objek.
Varian 1 : ' Objek baru () ' -> Konstruktor objek tanpa argumen.
Varian 2 : ' Objek baru (orang) ' -> Konstruktor objek dengan argumen.
Varian 3.1 : ' Object.create (person) '. Gunakan Object.create dengan objek 'orang' sederhana. 'Object.create (person)' akan membuat (dan mengembalikan) objek kosong baru dan menambahkan properti '__proto__' ke objek kosong baru yang sama. Properti ini '__proto__' akan menunjuk ke objek 'orang'.
Varian 3.2 : ' Object.create (Object.prototype) '. Gunakan Object.create dengan objek bawaan -> 'Object.prototype'. 'Object.create (Object.prototype)' akan membuat (dan mengembalikan) objek kosong baru dan menambahkan properti '__proto__' ke objek kosong baru yang sama. Properti ini '__proto__' akan menunjuk ke objek 'Object.prototype'.
Varian 4 : 'Beberapa Fungsi baru () '
sumber
Secara internal
Object.create
melakukan ini:Sintaks hanya menghilangkan ilusi bahwa JavaScript menggunakan Warisan Klasik.
sumber
Object.create
, melakukan lebih dari itu, Anda dapat mendefinisikan properti berdasarkan deskriptor properti dan Anda dapat membuat objek yang tidak mewarisi dari apa pun (Object.create(null);
), jenis shim ini harus dihindari karena Anda tidak dapat benar-benar meniru itu perilaku pada ES3. Info lebih lanjutObject.create
.Sesuai dengan jawaban ini dan kata kunci video ini
new
melakukan hal-hal berikut:Menciptakan objek baru.
Menautkan objek baru ke fungsi konstruktor (
prototype
).Membuat
this
titik variabel ke objek baru.Menjalankan fungsi konstruktor menggunakan objek baru dan melakukan implisit
return this
;Menetapkan nama fungsi konstruktor ke properti objek baru
constructor
.Object.create
hanya melakukan1st
dan2nd
melangkah !!!sumber