Deskriptor harta ialah konsep baharu dalam ES5 Fungsinya adalah untuk menambah lebih kawalan pada sifat objek.
Object.defineProperty
Untuk mengkaji deskriptor sifat, kita mesti bercakap tentang kaedah Object.defineProperty dahulu. Tujuan kaedah ini adalah untuk menentukan sifat baharu untuk objek atau mengubah suai sifat sedia ada. Prototaipnya adalah seperti berikut:
Object.defineProperty(obj, prop, deskriptor)
Contoh penggunaan:
var obj = { };
Object.defineProperty(obj, 'attr', { value: 1 });
Sekeping kod di atas menambah atribut bernama attr dengan nilai 1 pada objek obj. Bersamaan dengan:
var obj = { };
obj.attr = 1;
Sebagai perbandingan, kaedah penulisan Object.defineProperty nampaknya lebih rumit. Walau bagaimanapun, rahsia terbesarnya terletak pada parameter ketiganya.
Penerangan Data
Andaikan kita mahu attr menjadi atribut baca sahaja, kita boleh menambah deskriptor data boleh tulis:
var obj = { };
Object.defineProperty(obj, 'attr', {
Nilai: 1,
boleh ditulis: palsu
});
console.log(obj.attr);
obj.attr = 2; // gagal
console.log(obj.attr);
Dengan melaksanakan program di atas, anda boleh mendapati bahawa nilai attr yang dicetak dua kali ialah 1, yang bermaksud bahawa penulisan atribut gagal. Walau bagaimanapun, keputusan sedemikian akan menjadi agak membingungkan, kerana pernyataan tugasan gagal dilaksanakan tanpa pengecualian. Bayangkan jika masalah sedemikian berlaku dalam sekeping kod yang besar, ia akan menjadi sukar untuk menyelesaikan masalah. Malah, hanya menjalankan kod dalam mod ketat akan menghasilkan pengecualian:
'gunakan ketat'; // Masukkan mod ketat
var obj = { };
Object.defineProperty(obj, 'attr', {
Nilai: 1,
boleh ditulis: palsu
});
obj.attr = 2; // pengecualian lontaran
Mari kita lihat satu lagi deskriptor data yang boleh dikira, yang boleh mengawal sama ada harta itu boleh dikira. Jika anda hanya mentakrifkan atribut, atribut ini boleh disenaraikan dalam gelung untuk...dalam:
var obj = { };
obj.attr = 1;
untuk (var i dalam obj) { console.log(obj[i]);
enumerable boleh "menyembunyikan":
var obj = { };
Object.defineProperty(obj, 'attr', {
Nilai: 1,
boleh dikira: palsu
});
untuk (var i dalam obj) { console.log(obj[i]);
Apabila anda melaksanakan kod di atas, anda akan mendapati bahawa konsol tidak mengeluarkan apa-apa kerana atribut attr tidak boleh dikira pada masa ini.
Pada ketika ini, anda mungkin mempunyai soalan, bolehkah deskriptor atribut diubah suai? Sebagai contoh, bolehkah sifat baca sahaja ditakrifkan sebagai boleh ditulis semula? Malah, ini bergantung pada deskriptor data lain yang boleh dikonfigurasikan, yang mengawal sama ada deskriptor harta boleh ditukar.
var obj = { };
Object.defineProperty(obj, 'attr', {
Nilai: 1,
boleh ditulis: palsu,
boleh dikonfigurasikan: benar
});
Object.defineProperty(obj, 'attr', {
boleh ditulis: benar
});
obj.attr = 2;
Kod di atas mula-mula mentakrifkan attr sebagai atribut baca sahaja, dan kemudian mentakrifkannya semula sebagai boleh ditulis. Jadi penulisan kepada attr berjaya.
Penerangan Akses
Deskriptor akses adalah serupa dengan mendapatkan/menetapkan aksesori dalam berorientasikan objek.
var obj = { };
Object.defineProperty(obj, 'attr', {
set: function(val) { this._attr = Math.max(0, val },
Dapatkan: function() { return this._attr;
});
obj.attr = -1;
console.log(obj.attr); // 0
Dalam sekeping kod di atas, akses kepada attr sebenarnya menjadi akses kepada _attr, dan nilai minimum dihadkan kepada 0 dalam fungsi yang ditetapkan.
Dapatkan deskriptor atribut
Perkara di atas adalah mengenai menetapkan deskriptor atribut, jadi bagaimana untuk mendapatkan deskriptor yang ditetapkan? Object.getOwnPropertyDescriptor melakukan tugasnya.
var obj = { };
Object.defineProperty(obj, 'attr', {
Nilai: 1,
boleh ditulis: palsu,
boleh dikonfigurasikan: benar
});
var desc = Object.getOwnPropertyDescriptor(obj, 'attr');
console.dir(desc);
Kawalan Objek
Object.defineProperty yang disebut sebelum ini beroperasi pada sifat objek, manakala tiga kaedah yang dinyatakan di bawah beroperasi pada objek secara langsung.
Object.preventExtensions boleh menghalang objek daripada mempunyai sifat baharu:
var obj = { };
obj.attr = 1;
Object.preventExtensions(obj);
obj.attr2 = 2; //gagal
Object.seal
boleh menjadikan objek hanya mempunyai nilai atribut yang boleh diubah suai (jika atribut dibaca sahaja, malah nilai atribut tidak boleh diubah suai):
var obj = { };
obj.attr = 1;
Object.seal(obj);
obj.attr = 1.5;
padam obj.attr; // gagal
Object.freeze
boleh menjadikan objek tidak boleh diubah suai sepenuhnya:
var obj = { };
obj.attr = 1;
Object.freeze(obj);
obj.attr = 1.5; // gagal
obj.attr2 = 2; //gagal
Kemudian anda mungkin bertanya, bagaimana anda tahu sama ada objek telah dihalang Sambungan, dimeterai atau dibekukan? Jawapannya ialah untuk memanggil Object.isExtensible, Object.isSealed, dan Object.isFrozen masing-masing Penggunaan ketiga-tiga fungsi ini agak mudah dan tidak lagi menyusahkan.
Secara amnya, objek boleh dikawal dengan lebih lanjut melalui deskriptor atribut dan ketelitian logik program boleh diperkukuh. Satu-satunya kelemahan ialah ES5 hanya dilaksanakan dalam IE9 (IE9 belum lagi menyokong mod yang ketat). IE8 Walaupun bahagiannya masih agak tinggi, set perkara ini pada masa ini hanya boleh digunakan dalam penyemak imbas mudah alih dan Node.js.