Padamkan kunci di tengah-tengah pengetahuan Javascript Object_Basic

WBOY
Lepaskan: 2016-05-16 16:30:58
asal
1642 orang telah melayarinya

Anda juga tidak boleh melakukan ini, pulang ke rumah dan bertani

Salin kod Kod adalah seperti berikut:

padam thisIsObject[key]
atau
padam thisIsObject.key

Dengan cara ini, mari kita bercakap tentang cara menggunakan padam

Beberapa minggu yang lalu, saya berpeluang melihat buku Stoyan Stefanov Object-Oriented Javascript Buku ini mempunyai penarafan tinggi di Amazon (12 ulasan, 5 bintang), jadi saya ingin tahu sama ada ia seperti itu. buku yang disyorkan, saya mula membaca bab tentang fungsi. Saya sangat menyukai cara buku ini menerangkan perkara, dan contoh-contohnya disusun dengan cara yang sangat bagus dan progresif pengetahuan dengan mudah Walau bagaimanapun, hampir serta-merta, saya menemui salah faham yang menarik yang berulang sepanjang bab - memadamkan fungsi fungsi Terdapat juga beberapa ralat lain (seperti pengisytiharan fungsi dan ungkapan fungsi), tetapi kami tidak akan membincangkannya buat masa ini. .

Buku ini mendakwa:

"Sesuatu fungsi dianggap seperti pembolehubah biasa - ia boleh disalin ke pembolehubah lain atau dipadamkan".

Salin kod Kod adalah seperti berikut:
var sum = function(a, b) {kembali a b;}
var tambah = jumlah;
padamkan jumlah
benar
jenis jumlah;
"tidak ditentukan"

Abaikan beberapa titik koma yang hilang, bolehkah anda melihat di mana ralat dalam baris kod ini Jelas sekali, ralatnya ialah pemadaman pembolehubah jumlah tidak akan berjaya "tidak ditentukan" sama ada kerana pemadaman pembolehubah tidak boleh dilakukan dalam JavaScript Sekurang-kurangnya, bukan dengan cara pengisytiharan ini.

Jadi, apakah sebenarnya yang berlaku dalam contoh ini? Adakah ia satu pepijat Atau adakah ia adalah penggunaan khas Mungkin bukan kod ini sebenarnya dalam konsol Firebug, dan Stoyan mesti menggunakannya sebagai alat ujian pantas. Ia hampir seolah-olah Firebug mematuhi beberapa peraturan pemadaman yang lain yang menyebabkan Stoyan sesat

Sebelum menjawab soalan ini, kami terlebih dahulu perlu memahami cara pengendali padam berfungsi dalam JavaScript: Apa yang boleh dipadamkan dan apa yang tidak boleh dipadamkan Hari ini, saya akan cuba menerangkan soalan ini secara terperinci Tingkah laku "pelik" dan menyedari bahawa ia tidak begitu pelik selepas semua Keserasian penyemak imbas dan beberapa pepijat yang paling terkenal Kami juga akan membincangkan mod ketat ES5 dan cara ia mengubah tingkah laku pengendali padam.

Saya akan menggunakan JavaScript dan ECMAScript secara bergantian, kedua-duanya bermaksud ECMAScript (melainkan jelas bercakap tentang pelaksanaan JavaScript Mozilla)

Tidak menghairankan, penjelasan mengenai pemadaman agak terhad di web Artikel MDC mungkin merupakan sumber terbaik untuk difahami, tetapi, malangnya, ia kehilangan beberapa butiran menarik mengenai perkara itu. Ya, salah satu perkara yang terlupa bertanggungjawab untuk tingkah laku pelik Firebug Dan rujukan MSDN hampir tidak berguna dalam aspek ini

Teori

Jadi, mengapa kita boleh memadamkan sifat objek:

Salin kod Kod adalah seperti berikut: var o = { x: 1 };
padam o.x; // benar
o.x; // tidak ditentukan



Tetapi objek yang diisytiharkan seperti ini tidak boleh dipadamkan:

Salin kod Kod adalah seperti berikut: var x = 1;
padamkan x; // palsu
x; // 1



Atau fungsi:

Salin kod Kod adalah seperti berikut: fungsi x(){}
padamkan x; // palsu
jenis x; // "fungsi"

Nota: Apabila atribut tidak boleh dipadamkan, operator padam hanya akan mengembalikan palsu

Untuk memahami perkara ini, pertama sekali kita perlu memahami konsep ini tentang contoh pembolehubah dan sifat sifat - konsep yang, malangnya, jarang disebut dalam buku JavaScript, saya akan cuba menerangkannya dalam beberapa perenggan seterusnya Tinjau secara ringkas konsep ini konsep sukar difahami! Jika anda tidak mengambil berat tentang "mengapa perkara ini berfungsi dengan cara yang betul", sila langkau bab ini

Jenis kod:

Dalam ECMAScript, terdapat 3 jenis kod boleh laku yang berbeza: Kod global, Kod fungsi dan kod Eval Jenis ini lebih kurang sama dalam nama, berikut ialah gambaran ringkas:

Apabila sekeping kod sumber dilihat sebagai program, ia akan dilaksanakan dalam persekitaran global dan dianggap kod global Dalam persekitaran penyemak imbas, kandungan elemen skrip biasanya Ditafsirkan sebagai program dan oleh itu dilaksanakan sebagai global kod.

Sebarang kod yang dilaksanakan secara langsung dalam fungsi jelas dianggap kod fungsi Dalam penyemak imbas, kandungan atribut acara (seperti

) biasanya Ditafsirkan ke dalam kod fungsi.

Akhir sekali, teks kod yang digunakan pada fungsi eval terbina dalam ditafsirkan sebagai kod Eval Tidak lama lagi kita akan mengetahui sebab jenis ini istimewa.

Konteks pelaksanaan:

Apabila kod ECMAScript dilaksanakan, ia biasanya berlaku dalam konteks pelaksanaan khusus ialah konsep entiti yang agak abstrak yang membantu memahami cara skop (Skop) dan instantiasi berubah (Instasiasi Pembolehubah) berfungsi kod boleh laku, terdapat konteks pelaksanaan yang sepadan dengannya Apabila fungsi dilaksanakan, kita katakan bahawa "kawalan program memasuki konteks pelaksanaan kod fungsi"; apabila sekeping kod global dilaksanakan, Kawalan program memasuki konteks pelaksanaan kod global, dsb.

Seperti yang anda lihat, konteks pelaksanaan secara logiknya boleh membentuk timbunan Pertama, mungkin terdapat sekeping kod global dengan konteks pelaksanaannya sendiri, dan kemudian sekeping kod itu mungkin memanggil fungsi, mengambilnya dengan konteks pelaksanaan . Fungsi ini boleh memanggil fungsi lain, dsb. Walaupun fungsi itu dipanggil secara rekursif, ia akan memasuki konteks pelaksanaan baharu setiap kali ia dipanggil

Objek pengaktifan/Objek Pembolehubah:

Setiap konteks pelaksanaan mempunyai objek yang dipanggil pembolehubah yang dikaitkan dengannya Sama seperti konteks pelaksanaan, objek pembolehubah ialah entiti abstrak, mekanisme yang digunakan untuk menerangkan kejadian pembolehubah Perkara yang menarik ialah, Pembolehubah dan fungsi yang diisytiharkan dalam kod sumber biasanya ditambahkan pada objek pembolehubah ini sebagai sifat

Apabila kawalan program memasuki konteks pelaksanaan kod global, objek global digunakan sebagai objek berubah Inilah sebabnya pembolehubah fungsi yang diisytiharkan sebagai global menjadi sifat objek global.

/* ingat bahawa `ini` merujuk kepada objek global apabila dalam skop global */
var GLOBAL_OBJECT = ini;

var foo = 1; GLOBAL_OBJECT.foo; // 1

foo === GLOBAL_OBJECT.foo; // benar

bar fungsi(){}

jenis GLOBAL_OBJECT.bar; // "fungsi"

GLOBAL_OBJECT.bar === bar; // true


Baiklah, jadi pembolehubah global menjadi sifat objek global, tetapi apa yang berlaku kepada pembolehubah tempatan (yang ditakrifkan dalam kod fungsi) Mereka sebenarnya berkelakuan sangat serupa: mereka menjadi objek berubah (Objek Pembolehubah). dalam kod fungsi, objek berubah bukan objek global, tetapi objek pengaktifan dipanggil setiap kali ia memasuki konteks pelaksanaan kod fungsi.

Bukan sahaja pembolehubah dan fungsi yang diisytiharkan dalam kod fungsi akan menjadi sifat objek aktif ini juga akan dilakukan dalam setiap parameter fungsi (bersamaan dengan nama parameter formal yang sepadan) dan objek Argumen khas (dengan argumen; sebagai nama). Harap maklum bahawa objek aktif ialah mekanisme penerangan dalaman dan tidak boleh diakses daripada kod program

Salin kod Kod adalah seperti berikut:

(fungsi(foo){
bar var = 2;
function baz(){}
/*
Dalam istilah abstrak,
Objek `argumen` khas menjadi sifat yang mengandungi objek Pengaktifan fungsi:
ACTIVATION_OBJECT.arguments; // Arguments object
...serta hujah `foo`:
ACTIVATION_OBJECT.foo; // 1
...serta `bar` pembolehubah:
ACTIVATION_OBJECT.bar; // 2
...serta fungsi yang diisytiharkan secara tempatan:
Jenis ACTIVATION_OBJECT.baz; // "fungsi"
*/
})(1);

Akhir sekali, pembolehubah yang diisytiharkan dalam kod Eval menjadi sifat objek pembolehubah bagi konteks panggilan hanya menggunakan objek pembolehubah konteks pelaksanaan kod yang memanggilnya

Salin kod Kod adalah seperti berikut:
var GLOBAL_OBJECT = ini;
/* `foo` dicipta sebagai sifat memanggil objek Pembolehubah konteks,
yang dalam kes ini ialah objek Global */
eval('var foo = 1;');
GLOBAL_OBJECT.foo; // 1
(fungsi(){
/* `bar` dicipta sebagai sifat memanggil objek Pembolehubah konteks,
Yang dalam kes ini ialah objek Pengaktifan yang mengandungi fungsi */
eval('bar bar = 1;');
/*
Dalam istilah abstrak,
ACTIVATION_OBJECT.bar; // 1
*/
})();

Atribut harta

Sekarang kita mempunyai idea yang jelas tentang perkara yang berlaku kepada pembolehubah (ia menjadi sifat), satu-satunya konsep yang perlu difahami ialah atribut sifat Setiap Sifat boleh mempunyai sifar atau lebih atribut, dipilih daripada set berikut: ReadOnly, DontEnum, DontDelete dan Internal Anda boleh menganggapnya sebagai bendera - atribut mungkin ada atau mungkin tidak ada dalam atribut Bagi kami Untuk perbincangan hari ini, kami hanya berminat dengan DontDelete.

Apabila pembolehubah dan fungsi yang diisytiharkan menjadi atribut objek pembolehubah (atau objek aktif kod fungsi, atau objek global kod global), atribut ini dicipta dengan atribut DontDelete Walau bagaimanapun, sebarang Sifat eksplisit dicipta oleh (atau tersirat) penetapan sifat tidak akan mempunyai atribut DontDelete Inilah sebabnya kami boleh memadamkan beberapa sifat, tetapi bukan yang lain

var GLOBAL_OBJECT = ini;
/* `foo` ialah sifat objek Global.
Ia dicipta melalui pengisytiharan berubah-ubah dan begitu juga dengan atribut DontDelete.
Inilah sebabnya ia tidak boleh dipadamkan */
var foo = 1;
padam foo; // palsu
jenis foo; // "nombor"
/* `bar` ialah sifat objek Global.
Ia dicipta melalui pengisytiharan fungsi dan begitu juga dengan atribut DontDelete.
Inilah sebabnya ia tidak boleh dipadamkan sama ada */
bar fungsi(){}
padam bar; // palsu
jenis bar; // "fungsi"
/* `baz` juga merupakan sifat objek Global.
Walau bagaimanapun, ia dicipta melalui penetapan harta dan tidak mempunyai atribut DontDelete.
Inilah sebabnya ia boleh dipadamkan */
GLOBAL_OBJECT.baz = 'bla';
padam GLOBAL_OBJECT.baz; // benar
jenis GLOBAL_OBJECT.baz; // "undefined"


Objek terbina dalam dan DontDelete

Jadi, ini semua tentangnya (DontDelete): atribut khas atribut, digunakan untuk mengawal sama ada atribut ini boleh dipadamkan. Sila ambil perhatian bahawa beberapa atribut objek terbina dalam ditentukan untuk mengandungi DontDelete, jadi ia tidak boleh dipadamkan . Contohnya Pembolehubah argumen khas (atau, seperti yang kita ketahui, sifat objek aktif) mempunyai sifat DontDelete

Salin kod Kod adalah seperti berikut: (fungsi(){
/* tidak boleh memadam `argumen`, kerana ia mempunyai DontDelete */
padamkan argumen; // palsu
jenis argumen; // "objek"
/* tidak boleh memadam `length` fungsi; ia juga mempunyai DontDelete */
fungsi f(){}
padamkan f.length; // palsu
jenis f.panjang; // "nombor"
})();

Atribut yang sepadan dengan parameter fungsi juga mempunyai atribut DontDelete sejak penciptaannya, jadi kami tidak boleh memadamkannya.

Salin kod Kod adalah seperti berikut:

(fungsi(foo, bar){
padam foo; // palsu
foo; // 1
padam bar; // palsu
bar; // 'bla'
})(1, 'bla');

Tugasan tidak diisytiharkan:

Anda mungkin ingat bahawa tugasan yang tidak diisytiharkan mencipta sifat pada objek global, melainkan harta itu sudah ditemui di tempat lain dalam rantaian skop sebelum objek global Dan, kini kita tahu tentang penetapan harta dan pembolehubah Perbezaan antara pengisytiharan - yang terakhir akan menetapkan sifat DontDelete, tetapi yang pertama tidak

Salin kod Kod adalah seperti berikut:
var GLOBAL_OBJECT = ini;
/* cipta harta global melalui pengisytiharan berubah-ubah mempunyai DontDelete */
var foo = 1;
/* cipta harta global melalui tugasan yang tidak diisytiharkan tidak mempunyai DontDelete */
bar = 2;
padam foo; // palsu
jenis foo; // "nombor"
padam bar; // benar
jenis bar; // "tidak ditentukan"

Sila ambil perhatian: Sifat ditentukan apabila harta itu dicipta dan tugasan berikutnya tidak akan mengubah suai sifat sifat sedia ada.

Salin kod Kod adalah seperti berikut:
/* `foo` dicipta sebagai sifat dengan DontDelete */
fungsi foo(){}
/* Tugasan kemudian tidak mengubah suai atribut DontDelete masih ada */
foo = 1;
padam foo; // palsu
jenis foo; // "nombor"
/* Tetapi menyerahkan kepada harta yang tidak wujud,
mencipta harta itu dengan atribut kosong (dan sebagainya tanpa DontDelete) */
this.bar = 1;
padam bar; // benar
jenis bar; // "tidak ditentukan"

Kekeliruan pepijat api:

Apa yang berlaku dalam Firebug? Mengapa pembolehubah yang diisytiharkan dalam konsol boleh dipadamkan? Pembolehubah yang diisytiharkan dalam Eval sebenarnya dicipta sebagai sifat tanpa atribut DontDelete.

Salin kod Kod adalah seperti berikut:
eval('var foo = 1;');
foo; // 1
padam foo; // benar
jenis foo; // "tidak ditentukan"

Juga, begitu juga, apabila dipanggil dalam kod fungsi:

Salin kod Kod adalah seperti berikut:
(fungsi(){
eval('var foo = 1;');

foo; // 1
padam foo; // benar
jenis foo; // "tidak ditentukan"

})();


Ini adalah asas untuk kelakuan abnormal Firebug Semua teks dalam konsol akan dihuraikan dan dilaksanakan sebagai kod Eval, bukannya kod global atau fungsi Jelas sekali, semua pembolehubah yang diisytiharkan di sini akhirnya akan menjadi sifat tanpa atribut DontDelete semuanya boleh dipadamkan dengan mudah. ​​Kita perlu memahami perbezaan antara ini dalam kod global dan konsol Firebug.

Padamkan pembolehubah melalui Eval:

Tingkah laku eval yang menarik ini, ditambah dengan satu lagi aspek ECMAScript, secara teknikal boleh membenarkan kami mengalih keluar atribut "tidak boleh padam" Perkara mengenai pengisytiharan fungsi ialah ia boleh mengatasi pembolehubah dengan nama yang sama dalam konteks pelaksanaan yang sama.

Salin kod Kod adalah seperti berikut:
fungsi x(){ }
var x;
jenis x; // "fungsi"

Perhatikan cara pengisytiharan fungsi diutamakan dan mengatasi pembolehubah dengan nama yang sama (atau, dalam erti kata lain, sifat yang sama dalam objek pembolehubah Ini kerana pengisytiharan fungsi dibuat seketika selepas perisytiharan pembolehubah, dan dibenarkan). Mengatasinya (pengisytiharan pembolehubah) bukan sahaja menggantikan nilai harta, ia juga menggantikan atribut harta itu Jika kita mengisytiharkan fungsi melalui eval, fungsi itu harus menggantikannya dengan atribut asal (digantikan) juga, memandangkan pembolehubah yang diisytiharkan melalui eval mencipta sifat tanpa atribut DontDelete, membuat instantiating fungsi baharu ini sebenarnya akan mengalih keluar atribut DontDelete yang sedia ada daripada atribut, sekali gus menjadikan sifat A boleh dipadamkan (dan, jelas sekali, menunjukkan nilainya kepada fungsi yang baru dicipta).

Salin kod Kod adalah seperti berikut:

var x = 1;
/* Tidak boleh padam, `x` mempunyai DontDelete */
padamkan x; // palsu
jenis x; // "nombor"
eval('fungsi x(){}');
/* Harta `x` kini merujuk kepada fungsi dan sepatutnya tidak mempunyai DontDelete */
jenis x; // "fungsi"
padamkan x; // sepatutnya `benar`
jenis x; // seharusnya "tidak ditentukan"

Malangnya, "penipu" ini tidak berfungsi dalam mana-mana pelaksanaan semasa Mungkin saya kehilangan sesuatu di sini, atau tingkah lakunya sangat kabur sehingga pelaksana tidak menyedarinya.

Keserasian pelayar:

Memahami cara perkara berfungsi secara teori adalah berguna, tetapi amalan adalah yang paling penting Adakah penyemak imbas mengikut piawaian apabila ia berkaitan dengan penciptaan/pemadaman pembolehubah/sifat Jawapannya ialah: Dalam kebanyakan kes, ya.

Saya menulis set ujian ringkas untuk menguji keserasian penyemak imbas dengan pengendali padam, termasuk ujian di bawah kod global, kod fungsi dan kod Eval Set ujian menyemak nilai pulangan dan nilai atribut pengendali padam sama ada (seperti yang sepatutnya ) benar-benar dipadamkan. Nilai pulangan padam tidak sepenting hasil sebenar. Tidak penting jika padam mengembalikan benar dan bukannya palsu, yang penting ialah mereka yang mempunyai atribut DontDelete tidak dipadamkan. dan sebaliknya.

Pelayar moden secara amnya agak serasi Kecuali untuk ciri eval yang saya nyatakan sebelum ini, penyemak imbas berikut melepasi semua set ujian: Opera 7.54, Firefox 1.0, Safari 3.1.2, Chrome 4.

Safari 2.x dan 3.0.4 menghadapi masalah memadamkan parameter fungsi; sifat ini nampaknya dicipta tanpa DontDelete, jadi mereka boleh dipadamkan Safari 2.x mempunyai lebih banyak masalah - memadam pembolehubah jenis bukan rujukan (cth: padam 1) akan membuang pengecualian; pengisytiharan fungsi akan mencipta sifat boleh dipadam (tetapi, peliknya, pengisytiharan pembolehubah tidak akan menjadi tidak boleh dipadam (tetapi pengisytiharan fungsi tidak akan dipadam).

Sama seperti Safari, Konqueror (3.5, bukan 4.3) akan membuang pengecualian apabila memadamkan jenis bukan rujukan (seperti: padam 1), dan tersilap menjadikan pembolehubah fungsi boleh dipadam.

Nota Penterjemah:

Saya menguji versi terbaharu chrome, firefox dan IE, dan pada asasnya mengekalkan pas kecuali 23 dan 24, yang gagal saya juga menguji UC dan beberapa penyemak imbas mudah alih, sebagai tambahan kepada penyemak imbas terbina dalam Nokia E72. Kecuali untuk Fail 15 dan 16, kebanyakan penyemak imbas terbina dalam yang lain mempunyai kesan yang sama seperti penyemak imbas desktop Tetapi perlu dinyatakan bahawa penyemak imbas terbina dalam Blackberry Curve 8310/8900 boleh melepasi ujian 23, yang mengejutkan saya.

Gecko DontDelete pepijat:

Pelayar Gecko 1.8.x - Firefox 2.x, Camino 1.x, Seamonkey 1.x, dsb. - mempamerkan pepijat yang sangat menarik, tugasan eksplisit kepada harta akan memadamkan Atribut DontDeletenya, walaupun atribut itu dicipta melalui pengisytiharan berubah-ubah atau pengisytiharan fungsi.

Salin kod Kod adalah seperti berikut:

fungsi foo(){}
padam foo; // palsu (seperti yang dijangkakan)
typeof foo; // "fungsi" (seperti yang dijangkakan)
/* kini berikan kepada harta secara eksplisit */
this.foo = 1; // tersilap mengosongkan atribut DontDelete
padam foo; // benar
jenis foo; // "tidak ditentukan"
/* ambil perhatian bahawa ini tidak berlaku apabila memberikan sifat secara tersirat */
bar fungsi(){}
bar = 1;
padam bar; // palsu
bar jenis; // "nombor" (walaupun tugasan menggantikan harta)

Anehnya, Internet Explorer 5.5 - 8 melepasi keseluruhan set ujian, kecuali memadam jenis bukan rujukan (cth: padam 1) akan memberikan pengecualian (sama seperti Safari lama Tetapi di bawah IE terdapat pepijat yang lebih serius). tidak begitu jelas. Pepijat ini berkaitan dengan objek Global.

Pepijat IE:

Keseluruhan bab ini adalah mengenai pepijat Internet Explorer Wow!

Dalam IE (sekurang-kurangnya IE 6-8), ungkapan berikut akan membuang pengecualian (apabila dilaksanakan dalam kod global):

ini.x = 1;
delete x; // TypeError: Object tidak menyokong tindakan ini
Yang ini juga, tetapi memberikan pengecualian berbeza, yang menjadikan perkara lebih menarik:

var x = 1;
delete this.x; // TypeError: Tidak boleh padam 'this.x'
Nampaknya dalam IE, pengisytiharan berubah dalam kod global tidak mencipta sifat pada objek global Mencipta harta melalui tugasan (this.x = 1) dan kemudian memadamkannya melalui padam x akan membuang ralat (var x = 1) dan kemudian padamkannya dengan memadam ini.x melemparkan ralat lain.

Tetapi bukan itu sahaja Mencipta sifat melalui tugasan eksplisit sebenarnya akan menyebabkan pengecualian dibuang pada pemadaman. Bukan sahaja terdapat ralat di sini, tetapi sifat yang dibuat nampaknya mempunyai atribut DontDelete. Patutlah.

ini.x = 1;

padam this.x; // TypeError: Object tidak menyokong tindakan ini
typeof x; // "nombor" (masih wujud, tidak dipadamkan seperti yang sepatutnya!)

padam x; // TypeError: Objek tidak menyokong tindakan ini
typeof x; // "nombor" (tidak dipadamkan lagi)
Sekarang, kami akan menganggap bahawa di bawah IE, tugasan yang tidak diisytiharkan (yang sepatutnya mencipta sifat pada objek global) sememangnya mencipta sifat boleh dipadam

x = 1;
padamkan x; // benar
jenis x; // "tidak ditentukan"
Walau bagaimanapun, jika anda memadamkan atribut ini melalui rujukan ini dalam kod global (padamkan ini.x), ralat yang serupa akan muncul.

x = 1;
delete this.x; // TypeError: Tidak boleh padam 'this.x'
Jika kita ingin menyamaratakan gelagat ini, nampaknya pemadaman pembolehubah daripada kod global menggunakan delete this.x tidak pernah berjaya Apabila sifat yang dipersoalkan dibuat melalui tugasan eksplisit (this.x = 1) delete akan menimbulkan ralat; dicipta oleh tugasan tidak diisytiharkan (x = 1) atau oleh pengisytiharan (var x = 1), padam membuang ralat lain.

padam x, sebaliknya, hanya perlu membuang ralat jika sifat itu dicipta oleh tugasan eksplisit - ini.x = 1. Jika sifat dicipta melalui pengisytiharan (var x = 1) , pemadaman tidak pernah berlaku, dan pemadaman dengan betul mengembalikan palsu Jika sifat dibuat melalui tugasan yang tidak diisytiharkan (x = 1), pemadaman berfungsi seperti yang diharapkan

Saya memikirkan isu ini sekali lagi pada bulan September, dan Garrett Smith mencadangkan bahawa di bawah IE,

"Objek pembolehubah global dilaksanakan sebagai objek JScript dan objek global dilaksanakan oleh hos".

Garrett menggunakan entri blog Eric Lippert sebagai rujukan.

Kita boleh lebih kurang mengesahkan teori ini dengan melaksanakan beberapa ujian Perhatikan bahawa ini dan tetingkap kelihatan menunjuk ke objek yang sama (jika kita boleh mempercayai operator ===), tetapi objek berubah (pengisytiharan fungsi Objek di mana. ia terletak) berbeza daripada yang ditunjukkan oleh ini.

Salin kod Kod adalah seperti berikut:
/* dalam kod Global */
function getBase(){ kembalikan ini;
getBase() === this.getBase(); // false this.getBase() === this.getBase(); // true

window.getBase() === this.getBase(); // true
window.getBase() === getBase(); // false

Salah Faham:

Keindahan memahami mengapa perkara berfungsi seperti yang mereka lakukan tidak boleh diremehkan Saya telah melihat beberapa salah tanggapan tentang pengendali padam di seluruh web Sebagai contoh, jawapan ini pada Stackoverflow (dengan rating yang mengejutkan tinggi), jelas Confidence

"Apabila operan sasaran bukan harta objek, padam hendaklah menjadi no-op".

Sekarang kita memahami teras kelakuan operasi padam, ralat jawapan ini menjadi jelas padam tidak membezakan antara pembolehubah dan sifat (sebenarnya, untuk pemadaman, kedua-duanya adalah jenis rujukan ) dan sebenarnya hanya mengambil berat tentang DontDelete. atribut (dan sama ada atribut itu sendiri wujud).

Ia juga sangat menarik untuk melihat pelbagai salah tanggapan yang dibalas oleh satu sama lain, dalam urutan yang sama, seorang mula-mula mencadangkan hanya memadamkan pembolehubah (yang tidak akan memberi kesan melainkan ia diisytiharkan dalam eval), manakala seorang lagi Memberi pembetulan pepijat menerangkan cara pemadaman boleh digunakan untuk memadam pembolehubah dalam kod global, tetapi bukan dalam kod fungsi

Berhati-hati dengan tafsiran JavaScript di Internet, pendekatan yang ideal adalah untuk sentiasa memahami sifat masalah ;)

padam dan Hos Objek:

Algoritma pemadaman adalah kira-kira seperti berikut:

Jika operan bukan jenis rujukan, kembalikan benar

Jika objek tidak mempunyai sifat langsung dengan nama ini, mengembalikan benar (seperti yang kita tahu, objek itu boleh menjadi objek aktif atau objek global)
Jika harta itu wujud tetapi mempunyai atribut DontDelete, kembalikan false
Dalam kes lain, padamkan atribut dan kembalikan benar
Walau bagaimanapun, kelakuan pengendali padam pada objek hos tidak dapat diramalkan Dan sebenarnya tidak ada yang salah dengan tingkah laku ini: (mengikut standard), objek hos dibenarkan untuk melaksanakan fungsi seperti baca (dalaman [[Dapatkan]]), tulis. (kaedah [[Put]] dalaman) dan padam (kaedah [[Padam]] dalaman) beberapa pengendali melaksanakan sebarang gelagat ini untuk tingkah laku tersuai [[Padam]] yang mengubah objek hos kepada Punca kekeliruan.

Kami telah melihat beberapa kebiasaan IE apabila memadamkan objek tertentu (jelas dilaksanakan sebagai objek hos) akan menimbulkan ralat Sesetengah versi Firefox akan membuang ralat apabila memadamkan window.location. Anda tidak boleh mempercayainya mengembalikan nilai padam apabila objek adalah objek hos Mari lihat apa yang berlaku dalam Firefox:

Salin kod Kod adalah seperti berikut:
/* "alert" ialah sifat langsung `window` (jika kita percaya `hasOwnProperty`) */
window.hasOwnProperty('alert'); // benar
padam window.alert; // benar

typeof window.alert; // "fungsi"

Memadamkan tetingkap.alert mengembalikan benar, walaupun tiada sebab sama sekali mengapa sifat ini harus menyebabkan hasil sedemikian. Ia akan diselesaikan kepada rujukan (jadi ia tidak akan kembali benar dalam langkah pertama. Ini adalah sifat langsung). daripada objek tetingkap (Jadi ia tidak akan kembali benar dalam langkah kedua).

Moral cerita ini ialah: Jangan sekali-kali mempercayai objek hos.

Mod ketat ES5:

Jadi, apakah yang dibawa oleh mod ketat ECMAScript 5 kepada kita. Ia memperkenalkan sangat sedikit ralat sintaks apabila ungkapan pengendali padam adalah rujukan langsung kepada pembolehubah, parameter fungsi atau pengecam fungsi akan dilemparkan , jika harta tersebut mempunyai atribut dalaman [[Configurable]] == false, ralat jenis akan dilemparkan.

(fungsi(foo){
"use strict"; // dayakan mod ketat dalam fungsi ini
bar var;
function baz(){}
delete foo; // SyntaxError (semasa memadamkan hujah)
bar padam; // SyntaxError (apabila memadam pembolehubah)
delete baz; // SyntaxError (apabila memadam pembolehubah yang dibuat dengan pengisytiharan fungsi)
/* `length` bagi contoh fungsi mempunyai { [[Configurable]] : false } */
padam (function(){}).length; // TypeError
})();

Selain itu, memadamkan pembolehubah yang tidak diisytiharkan (atau rujukan yang tidak dapat diselesaikan) juga akan menimbulkan ralat sintaks:

"gunakan ketat";
padamkan i_dont_exist; // SyntaxError
Tugasan yang tidak diisytiharkan berkelakuan serupa dengan pembolehubah yang tidak diisytiharkan dalam mod ketat (kecuali kali ini ia menimbulkan ralat rujukan dan bukannya ralat sintaks):

"gunakan ketat";
i_dont_exist = 1; // ReferenceError
Seperti yang anda faham sekarang, semua sekatan lebih kurang masuk akal, kerana pemadaman pembolehubah, pengisytiharan fungsi dan parameter menyebabkan banyak kekeliruan daripada mengabaikan pemadaman secara senyap, mod ketat mengambil langkah yang lebih agresif dan lebih Deskriptif.

Ringkasan:

Catatan blog ini akhirnya menjadi agak panjang, jadi saya tidak akan bercakap tentang perkara seperti memadamkan objek tatasusunan dengan pemadaman atau maksudnya Anda boleh merujuk artikel MDC untuk penjelasan khusus (atau membaca standard dan Lakukan eksperimen anda sendiri).

Berikut ialah ringkasan ringkas tentang cara pemadaman berfungsi dalam JavaScript:

Pengisytiharan pembolehubah dan fungsi ialah sifat objek aktif atau objek global
Atribut mempunyai beberapa ciri, antaranya DontDelete ialah ciri yang menentukan sama ada atribut boleh dipadamkan
Pengisytiharan pembolehubah dan fungsi dalam kod global atau berfungsi sentiasa mencipta sifat dengan atribut DontDelete.
Parameter fungsi sentiasa sifat objek aktif dan mempunyai DontDelete.
Pembolehubah dan fungsi yang diisytiharkan dalam kod Eval sentiasa dibuat tanpa sifat DontDelete
Sifat baharu tidak mempunyai atribut apabila ia dicipta (dan sudah tentu tiada DontDelete
). Objek hos dibenarkan untuk memutuskan cara bertindak balas terhadap operasi pemadaman.
Jika anda ingin lebih mengenali perkara yang diterangkan di sini, sila rujuk spesifikasi ECMA-262 edisi ke-3.

Saya harap anda menikmati artikel ini dan mempelajari sesuatu yang baharu. Sebarang pertanyaan, cadangan atau pembetulan dialu-alukan.

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan