Saya melihat sebuah rintisan kosong di MDN beberapa waktu yang lalu untuk Reflect
objek dalam javascript tetapi saya tidak bisa seumur hidup saya menemukan apa pun di Google. Hari ini saya menemukan http://people.mozilla.org/~jorendorff/es6-draft.html#sec-reflect-object ini dan kedengarannya mirip dengan objek Proxy selain dari fungsi realm dan loader.
Pada dasarnya, saya tidak tahu apakah halaman yang saya temukan ini hanya menjelaskan cara menerapkan Reflect atau jika saya tidak dapat memahami kata-katanya. Bisakah seseorang menjelaskan kepada saya secara umum apa metode Reflect
lakukan?
Misalnya, pada halaman yang saya temukan mengatakan bahwa pemanggilan Reflect.apply ( target, thisArgument, argumentsList )
akan "Mengembalikan hasil pemanggilan metode internal [[Call]] dari target dengan argumen thisArgument dan args." tetapi apa bedanya dengan hanya menelepon target.apply(thisArgument, argumentsList)
?
Memperbarui:
Terima kasih kepada @Blue, saya menemukan halaman ini di wiki
http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api&s=reflect
yang menurut pengetahuan saya terbaik mengatakan bahwa objek refleksi menyediakan versi metode dari semua tindakan yang dapat dijebak oleh proxy untuk mempermudah penerusan. Tapi itu nampaknya agak aneh bagi saya karena saya tidak melihat bagaimana itu sepenuhnya diperlukan. Tapi sepertinya melakukan lebih dari itu, terutama par yang mengatakan double-lifting
tapi itu menunjuk ke spesifikasi proxy lama /
sumber
Reflect
hanyalah wadah untukRealm
danLoader
objek, tetapi saya juga tidak tahu apa yang dilakukan oleh objek.Reflect.Loader
danReflect.Realm
ada hubungannya dengan fungsi modul overloading?isExtensible
,ownKeys
dll ES 6, dengan kelas yang sebenarnya, ini berguna untuk mengetahui lebih lanjut tentang kelas (target
di 16.1.2 saya pikir).Jawaban:
UPDATE 2015: Seperti yang ditunjukkan oleh jawaban ke - 7 , sekarang ES6 (ECMAScript 2015) telah diselesaikan, dokumentasi yang lebih sesuai sekarang tersedia:
Jawaban asli (untuk pemahaman (historis) dan contoh tambahan) :
The
Reflection proposal
tampaknya telah berkembang ke Draft ECMAScript 6 Keterangan . Dokumen ini saat ini menguraikan metodeReflect
-object dan hanya menyatakan hal berikut tentangReflect
-object itu sendiri:Namun demikian, ada penjelasan singkat tentang kegunaannya dalam ES Harmony :
Sehingga
Reflect
objek tersebut menyediakan sejumlah fungsi utilitas, banyak di antaranya tampak tumpang tindih dengan metode ES5 yang ditentukan pada Objek global.Namun, itu tidak benar-benar menjelaskan masalah apa yang ingin diselesaikan atau fungsionalitas apa yang ditambahkan. Saya curiga ini bisa digoyahkan dan memang, spesifikasi harmoni di atas terkait dengan 'non-normatif, perkiraan penerapan metode ini' .
Memeriksa kode itu dapat memberikan gagasan (lebih lanjut) tentang penggunaannya, tetapi untungnya ada juga wiki yang menguraikan sejumlah alasan mengapa objek Reflect berguna :
(Saya telah menyalin (dan memformat) teks berikut untuk referensi di masa mendatang dari itu sumber karena mereka adalah satu - satunya contoh yang dapat saya temukan. Selain itu, mereka masuk akal, sudah memiliki penjelasan yang baik dan menyentuh contoh pertanyaan
apply
.)Nilai kembali yang lebih berguna
Banyak operasi dalam
Reflect
mirip dengan operasi ES5 yang ditentukan padaObject
, sepertiReflect.getOwnPropertyDescriptor
danReflect.defineProperty
. Namun, sedangkanObject.defineProperty(obj, name, desc)
akan kembaliobj
ketika properti berhasil didefinisikan, atau melemparTypeError
sebaliknya,Reflect.defineProperty(obj, name, desc)
ditentukan untuk mengembalikan boolean yang menunjukkan apakah properti berhasil didefinisikan atau tidak. Ini memungkinkan Anda untuk memfaktorkan ulang kode ini:try { Object.defineProperty(obj, name, desc); // property defined successfully } catch (e) { // possible failure (and might accidentally catch the wrong exception) }
Untuk ini:
if (Reflect.defineProperty(obj, name, desc)) { // success } else { // failure }
Metode lain yang mengembalikan status sukses boolean adalah
Reflect.set
(untuk memperbarui properti),Reflect.deleteProperty
(untuk menghapus properti),Reflect.preventExtensions
(untuk membuat objek tidak dapat diperluas) danReflect.setPrototypeOf
(untuk memperbarui tautan prototipe objek).Operasi kelas satu
Di ES5, cara untuk mendeteksi apakah suatu objek
obj
mendefinisikan atau mewarisi nama properti tertentu adalah dengan menulis(name in obj)
. Demikian pula untuk menghapus properti, seseorang menggunakandelete obj[name]
. Meskipun sintaks khusus bagus dan pendek, itu juga berarti Anda harus secara eksplisit menggabungkan operasi ini dalam fungsi ketika Anda ingin meneruskan operasi sebagai nilai kelas satu.Dengan
Reflect
, operasi ini dengan mudah didefinisikan sebagai fungsi kelas satu:Reflect.has(obj, name)
adalah setara fungsional(name in obj)
danReflect.deleteProperty(obj, name)
merupakan fungsi yang melakukan hal yang sama sepertidelete obj[name].
Aplikasi fungsi yang lebih andal
Di ES5, ketika seseorang ingin memanggil fungsi
f
dengan sejumlah variabel argumen yang dikemas sebagai arrayargs
dan mengikatthis
nilainyaobj
, seseorang dapat menulis:Namun,
f
bisa jadi sebuah objek yang dengan sengaja atau tidak sengaja mendefinisikanapply
metodenya sendiri . Saat Anda benar-benar ingin memastikan bahwa fungsi built-inapply
dipanggil, seseorang biasanya menulis:Function.prototype.apply.call(f, obj, args)
Tidak hanya bertele-tele ini, dengan cepat menjadi sulit untuk dipahami. Dengan
Reflect
, sekarang Anda dapat melakukan panggilan fungsi yang andal dengan cara yang lebih singkat dan lebih mudah dipahami:Reflect.apply(f, obj, args)
Konstruktor argumen-variabel
Bayangkan Anda ingin memanggil fungsi konstruktor dengan sejumlah variabel argumen. Di ES6, berkat sintaks penyebaran baru, dimungkinkan untuk menulis kode seperti:
var obj = new F(...args)
Di ES5, ini lebih sulit untuk ditulis, karena seseorang hanya dapat menggunakan
F.apply
atauF.call
memanggil fungsi dengan sejumlah variabel argumen, tetapi tidak adaF.construct
fungsi kenew
fungsi dengan sejumlah variabel argumen. DenganReflect
, sekarang seseorang dapat menulis, di ES5:var obj = Reflect.construct(F, args)
Perilaku penerusan default untuk Perangkap proxy
Saat menggunakan
Proxy
objek untuk membungkus objek yang sudah ada, sangat umum untuk mencegat operasi, melakukan sesuatu, dan kemudian "melakukan hal default", yang biasanya menerapkan operasi yang dicegat ke objek yang dibungkus. Misalnya, saya ingin mencatat semua akses properti ke suatu objekobj
:var loggedObj = new Proxy(obj, { get: function(target, name) { console.log("get", target, name); // now do the default thing } });
The
Reflect
danProxy
API dirancang bersama-sama , sehingga untuk setiapProxy
perangkap, ada sebuah metode yang sesuai padaReflect
yang "melakukan hal yang default". Karenanya, setiap kali Anda merasa ingin "melakukan default" di dalam penangan Proxy, hal yang benar untuk dilakukan adalah selalu memanggil metode yang sesuai dalamReflect
objek:var loggedObj = new Proxy(obj, { get: function(target, name) { console.log("get", target, name); return Reflect.get(target, name); } });
Jenis pengembalian
Reflect
metode dijamin kompatibel dengan jenis pengembalianProxy
perangkap.Kontrol pengikatan pengakses ini
Di ES5, cukup mudah untuk melakukan akses properti umum atau pembaruan properti. Misalnya:
var name = ... // get property name as a string obj[name] // generic property lookup obj[name] = value // generic property update
Metode
Reflect.get
danReflect.set
memungkinkan Anda melakukan hal yang sama, tetapi sebagai tambahan menerima sebagai argumen opsional terakhir sebuahreceiver
parameter yang memungkinkan Anda menyetel secara eksplisitthis
-binding ketika properti yang Anda dapatkan / setel adalah pengakses:var name = ... // get property name as a string Reflect.get(obj, name, wrapper) // if obj[name] is an accessor, it gets run with `this === wrapper` Reflect.set(obj, name, value, wrapper)
Ini kadang-kadang berguna saat Anda membungkus
obj
dan Anda ingin pengiriman otomatis apa pun di dalam pengakses dirutekan ulang ke pembungkus Anda, misalnya jikaobj
didefinisikan sebagai:var obj = { get foo() { return this.bar(); }, bar: function() { ... } }
Menelepon
Reflect.get(obj, "foo", wrapper)
akan menyebabkanthis.bar()
panggilan dialihkan kewrapper
.Hindari warisan
__proto__
Pada beberapa browser,
__proto__
didefinisikan sebagai properti khusus yang memberikan akses ke prototipe objek. ES5 menstandarkan metode baruObject.getPrototypeOf(obj)
untuk menanyakan prototipe.Reflect.getPrototypeOf(obj)
tidak persis sama, kecuali ituReflect
juga mendefinisikan yang sesuaiReflect.setPrototypeOf(obj, newProto)
untuk menyetel prototipe objek. Ini adalah cara baru yang sesuai dengan ES6 untuk memperbarui prototipe objek.Perhatikan bahwa:
setPrototypeOf
juga ada diObject
(sebagai benar ditunjukkan oleh KNU 's komentar )!EDIT:
Catatan samping (menangani komentar ke Q): Ada jawaban singkat dan sederhana di 'Q: ES6 Modules vs HTML Imports' yang menjelaskan
Realms
danLoader
objek.Penjelasan lain ditawarkan oleh tautan ini :
Layak disebutkan:
semua ini masih dalam konsep, ini bukan spesifikasi yang terukir di batu!Ini ES6, jadi ingatlah kompatibilitas browser!Semoga ini membantu!
sumber
Reflect.apply
dantarget.apply
? Atau apa yang harus saya tambahkan sebelum bounty berakhir?Object
.Reflect.get
sebagai implementasi default untuk proxy get tidak berfungsi dengan baik jika Anda membuat proxy objek dengan properti prototipe. Itu hanya mengeluh bahwa itu tidak berhasil. Namun jika Anda malah menggunakanReflect.get(target, property)
tanpa melewatkanreceiver
, maka itu berhasil.target
adalah target asli yang dibungkus proxy, sedangkanreceiver
proxy itu sendiri. Tetapi sekali lagi ini bisa berbeda jika Anda mengelola untuk mengakses properti secara berbeda.Mengikuti draf dokumen yang ditemukan di wiki,
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
Kami mendapatkan baris tentang "satu objek biasa" yang dijelaskan dalam draf. Ia juga memiliki definisi fungsi.
Wiki harus dapat diandalkan karena Anda dapat menemukan tautannya dari situs web emcascript
http://www.ecmascript.org/dev.php
Saya menemukan tautan pertama oleh google dan tidak beruntung menemukannya dengan mencari di wiki secara langsung.
sumber