Rumah hujung hadapan web tutorial js Pelajari Pepijat JScript dan Pengurusan Memori daripada kemahiran me_javascript

Pelajari Pepijat JScript dan Pengurusan Memori daripada kemahiran me_javascript

May 16, 2016 pm 03:31 PM
bug jscript Pengurusan ingatan

1. Pepijat JScript

Pelaksanaan ECMAScript JScript IE secara serius mengelirukan ungkapan fungsi bernama, menyebabkan ramai orang menentang ungkapan fungsi yang dinamakan, malah versi yang masih digunakan (versi 5.8 digunakan dalam IE8) masih wujud Soalan berikut.

Mari kita lihat apakah kesilapan yang dilakukan oleh IE dalam pelaksanaannya. Mari kita lihat contoh berikut:

Contoh 1: Pengecam ungkapan fungsi bocor ke skop luar

var f = function g(){};
typeof g; // "function"
Salin selepas log masuk

Kami berkata sebelum ini bahawa pengecam ungkapan fungsi yang dinamakan tidak sah dalam skop luaran, tetapi JScript jelas melanggar spesifikasi ini Pengecam g dalam contoh di atas dihuraikan ke dalam objek fungsi, yang berantakan -untuk-mencari pepijat disebabkan oleh sebab ini.

Nota: Masalah ini nampaknya telah dibetulkan dalam IE9

Contoh 2: Anggap ungkapan fungsi bernama sebagai pengisytiharan fungsi dan ungkapan fungsi

typeof g; // "function"
var f = function g(){};
Salin selepas log masuk

Dalam persekitaran ciri, pengisytiharan fungsi akan dihuraikan sebelum sebarang ungkapan Contoh di atas menunjukkan bahawa JScript sebenarnya menganggap ungkapan fungsi yang dinamakan sebagai pengisytiharan fungsi kerana ia menghuraikan g sebelum pengisytiharan sebenar.

Contoh ini membawa kepada contoh seterusnya.

Contoh 3: Ungkapan fungsi bernama mencipta dua objek fungsi yang berbeza sama sekali!

var f = function g(){};
f === g; // false
f.expando = 'foo';
g.expando; // undefined
Salin selepas log masuk

Melihat ini, semua orang akan menganggap bahawa masalahnya adalah serius, kerana mengubah suai mana-mana objek tidak akan mengubah yang lain Ini terlalu jahat. Melalui contoh ini, kita boleh mendapati bahawa mencipta dua objek yang berbeza, iaitu, jika anda ingin mengubah suai atribut f untuk menyimpan maklumat tertentu, dan kemudian menggunakannya sebagai satu perkara dengan merujuk atribut nama yang sama bagi g daripada objek yang sama, maka akan ada masalah besar kerana ia adalah mustahil.

Mari kita lihat contoh yang lebih rumit:

Contoh 4: Hanya menghuraikan pengisytiharan fungsi secara berurutan dan mengabaikan blok pernyataan bersyarat

var f = function g() {
  return 1;
};
if (false) {
 f = function g(){
 return 2;
 };
}
g(); // 2
Salin selepas log masuk

Pepijat ini jauh lebih sukar ditemui, tetapi punca pepijat adalah sangat mudah. Pertama, g dihuraikan sebagai pengisytiharan fungsi Memandangkan pengisytiharan fungsi dalam JScript tidak tertakluk kepada blok kod bersyarat, dalam cabang jika jahat ini, g dianggap sebagai fungsi lain g(){ return 2 }, juga Ia baru sahaja diisytiharkan semula. . Kemudian, semua ungkapan "biasa" dinilai, dan f diberi rujukan kepada objek lain yang baru dibuat. Memandangkan cabang jika keji "" tidak akan dimasukkan apabila ungkapan dinilai, f akan terus merujuk kepada fungsi fungsi pertama g(){ return 1 }. Selepas menganalisis ini, masalahnya adalah sangat jelas: jika anda tidak cukup berhati-hati dan panggil g dalam f, objek fungsi g yang tidak berkaitan akan dipanggil

.

Anda mungkin bertanya, apakah perbezaan apabila membandingkan objek berbeza dengan arguments.callee? Mari lihat:

var f = function g(){
  return [
  arguments.callee == f,
  arguments.callee == g
  ];
};
f(); // [true, false]
g(); // [false, true]
Salin selepas log masuk

Seperti yang anda lihat, rujukan arguments.callee sentiasa dipanggil fungsi Malah, ini juga merupakan perkara yang baik, seperti yang akan dijelaskan kemudian.

Satu lagi contoh menarik ialah menggunakan ungkapan fungsi bernama dalam pernyataan tugasan yang tidak mengandungi pengisytiharan:

(function(){
 f = function f(){};
})();
Salin selepas log masuk

Menurut analisis kod, kami pada asalnya ingin mencipta atribut global f (berhati-hati untuk tidak mengelirukannya dengan fungsi tanpa nama umum, yang menggunakan pengisytiharan bernama JScript yang membuat kucar-kacir di sini Ungkapan dihuraikan sebagai pengisytiharan fungsi, jadi f di sebelah kiri diisytiharkan sebagai pembolehubah tempatan (sama seperti pengisytiharan dalam fungsi tanpa nama umum Kemudian apabila fungsi itu dilaksanakan, f sudah ditakrifkan, dan fungsi f(). ) di sebelah kanan {} ditugaskan terus kepada pembolehubah tempatan f, jadi f bukan atribut global sama sekali.

Setelah memahami betapa tidak normalnya JScript, kita mesti menghalang masalah ini tepat pada masanya, pertama, mengelakkan pengecam daripada bocor ke dalam skop luaran. Kedua, pengecam yang digunakan sebagai nama fungsi tidak boleh disebut dalam contoh yang menjengkelkan g? ——Jika kita boleh berpura-pura bahawa g tidak wujud, berapa banyak masalah yang tidak perlu boleh dielakkan. Oleh itu, kuncinya ialah sentiasa merujuk kepada fungsi melalui f atau arguments.callee. Jika anda menggunakan ungkapan fungsi bernama, anda hanya perlu menggunakan nama itu semasa menyahpepijat. Akhir sekali, ingat untuk membersihkan fungsi yang telah dibuat secara tidak betul semasa pengisytiharan ungkapan fungsi bernama.

2. Pengurusan memori JScript

Setelah mengetahui pepijat penghuraian kod bukan standard ini, jika kita menggunakannya, kita akan mendapati bahawa sebenarnya terdapat masalah dengan ingatan Mari kita lihat contoh:

var f = (function(){
 if (true) {
 return function g(){};
 }
 return function g(){};
})();
Salin selepas log masuk

我们知道,这个匿名函数调用返回的函数(带有标识符g的函数),然后赋值给了外部的f。我们也知道,命名函数表达式会导致产生多余的函数对象,而该对象与返回的函数对象不是一回事。所以这个多余的g函数就死在了返回函数的闭包中了,因此内存问题就出现了。这是因为if语句内部的函数与g是在同一个作用域中被声明的。这种情况下 ,除非我们显式断开对g函数的引用,否则它一直占着内存不放。

var f = (function(){
 var f, g;
 if (true) {
 f = function g(){};
 }
 else {
 f = function g(){};
 }
 // 设置g为null以后它就不会再占内存了
 g = null;
 return f;
})();
Salin selepas log masuk

通过设置g为null,垃圾回收器就把g引用的那个隐式函数给回收掉了,为了验证我们的代码,我们来做一些测试,以确保我们的内存被回收了。

测试

测试很简单,就是命名函数表达式创建10000个函数,然后把它们保存在一个数组中。等一会儿以后再看这些函数到底占用了多少内存。然后,再断开这些引用并重复这一过程。下面是测试代码:

function createFn(){
 return (function(){
 var f;
 if (true) {
  f = function F(){
  return 'standard';
  };
 }
 else if (false) {
  f = function F(){
  return 'alternative';
  };
 }
 else {
  f = function F(){
  return 'fallback';
  };
 }
 // var F = null;
 return f;
 })();
}

var arr = [ ];
for (var i=0; i < 10000; i++) {
 arr[i] = createFn();
}

Salin selepas log masuk

通过运行在Windows XP SP2中的任务管理器可以看到如下结果:

IE7:

 without `null`: 7.6K -> 20.3K
 with `null`:  7.6K -> 18K

IE8:

 without `null`: 14K -> 29.7K
 with `null`:  14K -> 27K

Salin selepas log masuk

如我们所料,显示断开引用可以释放内存,但是释放的内存不是很多,10000个函数对象才释放大约3M的内存,这对一些小型脚本不算什么,但对于大型程序,或者长时间运行在低内存的设备里的时候,这是非常有必要的。

以上就是关于JScript的Bug与内存管理的全部介绍,希望对大家的学习有所帮助。

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

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Ringkasan pepijat Apple iOS18 Ringkasan pepijat Apple iOS18 Jun 14, 2024 pm 01:48 PM

Memandangkan persidangan WWDC Apple 2024 mencapai kesimpulan yang berjaya, bukan sahaja macos15 diumumkan, tetapi kemas kini sistem iOS18 baharu Apple paling menarik perhatian Walaupun terdapat banyak ciri baharu, sebagai versi pertama iOS18 Apple, orang ramai pasti tertanya-tanya sama ada ia adalah perlu untuk menaik taraf Apple iOS18, apakah jenis pepijat yang terdapat dalam keluaran terbaru Apple iOS18? Selepas penilaian penggunaan sebenar, berikut ialah ringkasan pepijat Apple iOS18, mari kita lihat. Pada masa ini, ramai pengguna iPhone tergesa-gesa untuk menaik taraf kepada iOS18 Namun, pelbagai pepijat sistem menyebabkan orang tidak selesa. Sesetengah penulis blog berkata bahawa anda harus berhati-hati semasa menaik taraf kepada iOS18 kerana "terdapat banyak pepijat." Blogger itu berkata bahawa jika iPhone anda adalah

Reka letak objek C++ diselaraskan dengan memori untuk mengoptimumkan kecekapan penggunaan memori Reka letak objek C++ diselaraskan dengan memori untuk mengoptimumkan kecekapan penggunaan memori Jun 05, 2024 pm 01:02 PM

Susun atur objek C++ dan penjajaran memori mengoptimumkan kecekapan penggunaan memori: Susun atur objek: ahli data disimpan dalam susunan pengisytiharan, mengoptimumkan penggunaan ruang. Penjajaran memori: Data diselaraskan dalam memori untuk meningkatkan kelajuan akses. Kata kunci alignas menentukan penjajaran tersuai, seperti struktur CacheLine yang dijajarkan 64 bait, untuk meningkatkan kecekapan akses talian cache.

Pengurusan Memori C++: Pembahagian Memori Tersuai Pengurusan Memori C++: Pembahagian Memori Tersuai May 03, 2024 pm 02:39 PM

Pengagih memori tersuai dalam C++ membenarkan pembangun melaraskan gelagat peruntukan memori mengikut keperluan Mencipta pengalokasi tersuai memerlukan pewarisan std::allocator dan menulis semula fungsi allocate() dan deallocate(). Contoh praktikal termasuk: meningkatkan prestasi, mengoptimumkan penggunaan memori dan melaksanakan tingkah laku tertentu. Apabila menggunakannya, penjagaan perlu diambil untuk mengelak membebaskan memori, mengurus penjajaran memori dan menjalankan penanda aras.

Amalan terbaik untuk peruntukan memori fungsi C++ dan pemusnahan dalam pangkalan kod yang besar Amalan terbaik untuk peruntukan memori fungsi C++ dan pemusnahan dalam pangkalan kod yang besar Apr 22, 2024 am 11:09 AM

Amalan terbaik untuk peruntukan dan pemusnahan memori fungsi C++ termasuk: menggunakan pembolehubah tempatan untuk peruntukan memori statik. Gunakan penunjuk pintar untuk peruntukan memori dinamik. Memori diperuntukkan dalam pembina dan dimusnahkan dalam pemusnah. Gunakan pengurus memori tersuai untuk senario memori yang kompleks. Gunakan pengendalian pengecualian untuk membersihkan sumber dan pastikan memori yang diperuntukkan dikeluarkan apabila pengecualian berlaku.

Sambungan dan teknik lanjutan untuk peruntukan dan pemusnahan memori fungsi C++ Sambungan dan teknik lanjutan untuk peruntukan dan pemusnahan memori fungsi C++ Apr 22, 2024 pm 05:21 PM

Pengurusan memori fungsi C++ menyediakan sambungan dan teknologi lanjutan, termasuk: Pengalokasi tersuai: membolehkan pengguna menentukan strategi peruntukan memori mereka sendiri. placementnew dan placementdelete: digunakan apabila objek perlu diperuntukkan ke lokasi memori tertentu. Teknologi lanjutan: kumpulan memori, penunjuk pintar dan RAII untuk mengurangkan kebocoran memori, meningkatkan prestasi dan memudahkan kod.

Cabaran dan tindakan balas pengurusan memori C++ dalam persekitaran berbilang benang? Cabaran dan tindakan balas pengurusan memori C++ dalam persekitaran berbilang benang? Jun 05, 2024 pm 01:08 PM

Dalam persekitaran berbilang benang, pengurusan memori C++ menghadapi cabaran berikut: perlumbaan data, kebuntuan dan kebocoran memori. Tindakan balas termasuk: 1. Menggunakan mekanisme penyegerakan, seperti mutex dan pembolehubah atom 2. Menggunakan struktur data tanpa kunci 3. Menggunakan penunjuk pintar 4. (Pilihan) Melaksanakan pengumpulan sampah;

Bagaimanakah pengurusan memori C++ berinteraksi dengan sistem pengendalian dan ingatan maya? Bagaimanakah pengurusan memori C++ berinteraksi dengan sistem pengendalian dan ingatan maya? Jun 02, 2024 pm 09:03 PM

Pengurusan memori C++ berinteraksi dengan sistem pengendalian, mengurus memori fizikal dan memori maya melalui sistem pengendalian, dan memperuntukkan dan melepaskan memori untuk program dengan cekap. Sistem pengendalian membahagikan memori fizikal kepada halaman dan menarik halaman yang diminta oleh aplikasi daripada memori maya mengikut keperluan. C++ menggunakan operator baharu dan padam untuk memperuntukkan dan melepaskan memori, meminta halaman memori daripada sistem pengendalian dan mengembalikannya masing-masing. Apabila sistem pengendalian membebaskan memori fizikal, ia menukar halaman memori yang kurang digunakan ke dalam memori maya.

Pengurusan memori fungsi golang dan goroutine Pengurusan memori fungsi golang dan goroutine Apr 25, 2024 pm 03:57 PM

Memori untuk fungsi dalam Go diluluskan oleh nilai dan tidak menjejaskan pembolehubah asal. Goroutine berkongsi memori, dan memori yang diperuntukkan tidak akan dituntut semula oleh GC sehingga Goroutine menyelesaikan pelaksanaan. Kebocoran memori boleh berlaku dengan memegang rujukan Goroutine yang lengkap, menggunakan pembolehubah global atau mengelakkan pembolehubah statik. Untuk mengelakkan kebocoran, adalah disyorkan untuk membatalkan Goroutines melalui saluran, mengelakkan pembolehubah statik dan menggunakan penyataan tangguh untuk mengeluarkan sumber.

See all articles