Artikel ini membawa anda pengetahuan yang berkaitan tentang javascript terutamanya memperkenalkan dan meringkaskan 10 petua pengoptimuman kod JavaScript. Artikel ini memperkenalkan kandungan secara terperinci di sekitar tema, yang mempunyai nilai rujukan tertentu semua orang.
[Cadangan berkaitan: tutorial video javascript, bahagian hadapan web]
Untuk mencapai pengoptimuman kod JavaScript, perkara pertama yang anda perlu lakukan ialah menguji masa pelaksanaan kod JavaScript dengan tepat. Sebenarnya, apa yang perlu dilakukan ialah mengumpul sejumlah besar sampel pelaksanaan untuk statistik dan analisis matematik Di sini kami menggunakan benchmark.js
untuk mengesan pelaksanaan kod.
Mula-mula kita perlu memasang kebergantungan dalam projek, kodnya adalah seperti berikut:
yarn add benchmark --save # 或者 npm i benchmark --save
Kemudian kami menulis kod ujian seperti berikut:
const Benchmark = require('benchmark') const suite = new Benchmark.Suite() // 添加测试 suite /** * add() 方法接受两个参数,其中第一个表示测试的名称,第二个表示测试的内容,他是一个函数* / .add('join1000', () => { new Array(1000).join(' ') }) .add('join10000', () => { new Array(10000).join(' ') }) // 添加时间监听 .on('cycle', event => { // 打印执行时间 console.log(String(event.target)) }) // 完成后执行触发的事件 .on('complete', () => { console.log('最快的是:' + suite.filter('fastest').map('name')) }) // 执行测试 .run({ async: true }) 复制代码
Hasil pelaksanaan kod adalah seperti berikut:
// join1000 x 146,854 ops/sec ±1.86% (88 larian sampel)
// join10000 x 16,083 ops/sec ±1.06% (92 larian sampel)
// Yang terpantas ialah: join1000
Dalam hasilnya, ops/sec
mewakili bilangan pelaksanaan sesaat, Sudah tentu, lebih besar lebih baik, diikuti dengan perbezaan peratusan antara masa pelaksanaan atas dan bawah sesaat, dan akhirnya kandungan dalam kurungan menunjukkan jumlah sampel. Kita boleh lihat prestasi join1000
lebih baik (saya rasa macam mengarut).
Pembolehubah global yang dinyatakan di sini harus digunakan dengan berhati-hati Mengapa kita harus menggunakannya dengan berhati-hati? Perkara utama adalah seperti berikut:
Mari kita tulis sekeping kod untuk melihat perbezaan kecekapan pelaksanaan antara pembolehubah global dan pembolehubah reka letak Kodnya adalah seperti berikut:
... suite .add('全局变量', () => { // 该函数内模拟全局作用域 let i, str = '' for (i = 0; i < 1000; i++) { str += i } }) .add('局部变量', () => { for (let i = 0, str = ''; i < 1000; i++) { str += i } }) ...
Keputusan berjalan kod adalah seperti berikut:
Pembolehubah global x 158,697 ops/s ±1.05% (87 larian sampel)
Pembolehubah setempat x 160,697 ops/sec ±1.03sec % (90 larian sampel)
Yang terpantas ialah: pembolehubah tempatan
Walaupun perbezaannya tidak besar, kita dapat merasakan bahawa prestasi pembolehubah global adalah lebih teruk daripada pembolehubah tempatan.
Apabila menambah kaedah yang diperlukan contohnya objek kepada pembina, cuba tambahkannya menggunakan prototaip dan bukannya menambahnya di dalam pembina Kita boleh melihat kod ujian berikut :
... suite .add('构造函数内部添加', () => { function Person() { this.sayMe = function () { return '一碗周' } } let p = new Person() }) .add('原型方式内部添加', () => { function Person() {} Person.prototype.sayMe = function () { return '一碗周' } let p = new Person() }) ...
Keputusan berjalan kod adalah seperti berikut:
Elakkan menggunakan kaedah akses harta Dalam objek dalam JavaScript, elakkan menggunakan beberapa kaedah akses harta Ini kerana semua sifat dalam JavaScript boleh dilihat secara luaran.x 573,786 ops/sec ±1.97% (89 larian sampel) ditambah di dalam pembina
Cara Prototaip untuk menambah secara dalaman Memandangkan penutupan akan menyebabkan pembolehubah dalam fungsi disimpan dalam ingatan, yang menggunakan banyak memori, penutupan tidak boleh disalahgunakan, jika tidak, ia akan menyebabkan masalah prestasi pada halaman web, malah boleh menyebabkan kepada kebocoran ingatan. Penyelesaiannya adalah untuk memadam semua pembolehubah tempatan yang tidak digunakan sebelum keluar dari fungsi (iaitu, menetapkan semula pembolehubah tempatan kepada
).
null
Hasil menjalankan kod adalah seperti berikut:
... suite .add('使用属性访问方法', () => { function Person() { this.name = '一碗周' this.getName = function () { return '一碗周' } } let p = new Person() let n = p.getName() }) .add('不使用属性访问方法', () => { function Person() { this.name = '一碗周' } let p = new Person() let n = p.name }) ...
Tanpa menggunakan kaedah capaian harta 🎜>untuk pengoptimuman gelung
Apabila kita menggunakan gelung for, kami boleh menyimpan beberapa data yang diperlukan, seperti atribut seperti, jadi kami tidak perlu mendapatkannya setiap kali kami menilai, dengan itu mengoptimumkan kod kami.
Kod sampel adalah seperti berikut:
Hasil jalankan kod adalah seperti berikut: arr.length
Jujukan ke hadapan x 1,322,889 ops /saat ±1.36% (86 larian sampel)Cache x 1,356,696 ops/saat ±0.70% (92 larian sampel)
Cara lain untuk menulis cache x 1,383,096 ops/sec 93 larian sampel)... suite .add('正序', () => { let arr = new Array(100) let str = '' for (let i = 0; i < arr.length; i++) { str += i } }) .add('缓存', () => { let arr = new Array(100) let str = '' for (let i = arr.length; i; i--) { str += i } }) .add('缓存的另一种写法', () => { let arr = new Array(100) let str = '' for (let i = 0, l = arr.length; i < l; i++) { str += i } }) ...
Pilih kaedah gelung optimum
Gelung yang biasa kita gunakan sekarang termasuk,
dan
Gelung, yang manakah antara jenis ini mempunyai prestasi terbaik Kod ujian adalah seperti berikut:
forEach x 4,248,577 ops/sec ±0.89% (86 runs sampled)
for...in x 4,583,375 ops/sec ±1.15% (91 runs sampled)
for x 1,343,871 ops/sec ±1.91% (88 runs sampled)
最快的是:for...in
由运行结果可以看出我们可以尽量使用for...in
或者forEach
循环,减少使用for
循环。
减少判断层级就是减少一些if
语句的嵌套,如果是一些必要的条件我们可以通过单层if
结合return
直接跳出函数的执行,关于优化前与优化后的代码执行比对如下所示:
... /*** 接收两类文件,zip 和 rar* 压缩包的大小限制为 10 兆* / suite .add('嵌套写法', () => { function uploadFile(suffix, size) { // 允许上传的后缀名 const suffixList = ['.zip', '.rar'] const M = 1024* 1024 if (suffixList.includes(suffix)) { if (size <= 10* M) { return '下载成功' } } } uploadFile('.zip', 1* 1024* 1024) }) .add('减少判断写法', () => { function uploadFile(suffix, size) { // 允许上传的后缀名 const suffixList = ['.zip', '.rar'] const M = 1024* 1024 if (!suffixList.includes(suffix)) return if (size > 10* M) return return '下载成功' } uploadFile('.zip', 1* 1024* 1024) }) ...
代码运行结果如下:
嵌套写法 x 888,445,014 ops/sec ±2.48% (88 runs sampled)
减少判断写法 x 905,763,884 ops/sec ±1.35% (92 runs sampled)
最快的是:减少判断写法,嵌套写法
虽然说差距并不是很大,但是不适用嵌套的代码比普通代码更优一些。
减少代码中作用域链的查找也是代码优化的一种方法,如下代码展示了两者的区别:
... suite .add('before', () => { var name = '一碗粥' function sayMe() { name = '一碗周' function print() { var age = 18 return name + age } print() } sayMe() }) .add('after', () => { var name = '一碗粥' function sayMe() { var name = '一碗周' // 形成局部作用域 function print() { var age = 18 return name + age } print() } sayMe() }) ...
代码运行结果如下:
before x 15,509,793 ops/sec ±7.78% (76 runs sampled)
after x 17,930,066 ops/sec ±2.89% (83 runs sampled)
最快的是:after
上面代码只是为了展示区别,并没有实际意义。
如果对象中的某个数据在一个代码块中使用两遍以上,这样的话将其进行缓存从而减少数据的读取次数来达到更优的一个性能,
测试代码如下:
... var userList = { one: { name: '一碗周', age: 18, }, two: { name: '一碗粥', age: 18, }, } suite .add('before', () => { function returnOneInfo() { userList.one.info = userList.one.name + userList.one.age } returnOneInfo() }) .add('after', () => { function returnOneInfo() { let one = userList.one one.info = one.name + one.age } returnOneInfo() }) ...
代码运行结果如下:
before x 222,553,199 ops/sec ±16.63% (26 runs sampled)
after x 177,894,903 ops/sec ±1.85% (88 runs sampled)
最快的是:before
凡是可以使用字面量方式声明的内容,绝对是不可以使用构造函数的方式声明的,两者在性能方面相差甚远,代码如下:
... suite .add('before', () => { var str = new String('string') }) .add('after', () => { var str = 'string' }) ...
代码运行结果如下:
before x 38,601,223 ops/sec ±1.16% (89 runs sampled)
after x 897,491,903 ops/sec ±0.92% (92 runs sampled)
最快的是:after
【相关推荐:javascript视频教程、web前端】
Atas ialah kandungan terperinci Ringkasan dan perkongsian 10 petua pengoptimuman kod JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!