Dieser Artikel vermittelt Ihnen relevantes Wissen über Javascript. Der Artikel stellt den Inhalt im Detail vor und ist für jeden hilfreich.
[Verwandte Empfehlungen: Javascript-Video-Tutorial, Web-Frontend]
Wenn Sie JavaScript-Code optimieren möchten, müssen Sie zunächst das JavaScript genau testen Code-Ausführungszeit. Tatsächlich muss eine große Anzahl von Ausführungsbeispielen für mathematische Statistiken und Analysen gesammelt werden. Hier verwenden wir benchmark.js
, um die Ausführung des Codes zu erkennen. benchmark.js
来检测代码的执行情况。
首先我们需要在项目中安装依赖,代码如下:
yarn add benchmark --save # 或者 npm i benchmark --save
然后我们写一个测试代码,如下所示:
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 }) 复制代码
代码执行结果如下:
// join1000 x 146,854 ops/sec ±1.86% (88 runs sampled)
// join10000 x 16,083 ops/sec ±1.06% (92 runs sampled)
// 最快的是:join1000
在结果中,ops/sec
表示的是每秒执行的次数,当然是越大越好,紧接着是每秒执行次数上下相差的百分比,最后括号中的内容表示共取样多少次。我们可以看到,都是join1000
的性能更好一些(我感觉我在说废话)。
这里所说的慎用全局变量,为什么要慎用呢?主要有以下几点:
下面我们就来写一段代码,看一下全局变量与布局变量在执行效率方面的差异,代码如下:
... suite .add('全局变量', () => { // 该函数内模拟全局作用域 let i, str = '' for (i = 0; i < 1000; i++) { str += i } }) .add('局部变量', () => { for (let i = 0, str = ''; i < 1000; i++) { str += i } }) ...
代码运行结果如下:
全局变量 x 158,697 ops/sec ±1.05% (87 runs sampled)
局部变量 x 160,697 ops/sec ±1.03% (90 runs sampled)
最快的是:局部变量
虽然说差异不大,但是我们可以感知全局变量比局部的性能更差一些。
为构造函数增加实例对象需要的方法时,尽量使用原型的方式添加,而不是构造函数内部进行添加,我们可以看如下测试代码:
... suite .add('构造函数内部添加', () => { function Person() { this.sayMe = function () { return '一碗周' } } let p = new Person() }) .add('原型方式内部添加', () => { function Person() {} Person.prototype.sayMe = function () { return '一碗周' } let p = new Person() }) ...
代码运行结果如下:
构造函数内部添加 x 573,786 ops/sec ±1.97% (89 runs sampled)
原型方式内部添加 x 581,693 ops/sec ±3.46% (80 runs sampled)
最快的是:构造函数内部添加
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,严重可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除 (即将局部变量重新赋值为null
)。
在JavaScript中的对象中,避免使用一些属性访问方法,这是因为JavaScript中的所有属性都是外部可见的。
示例代码如下:
... 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 }) ...
代码运行结果如下:
使用属性访问方法 x 406,682 ops/sec ±2.33% (82 runs sampled)
不使用属性访问方法 x 554,169 ops/sec ±2.03% (85 runs sampled)
最快的是:不使用属性访问方法
我们在使用for循环时,可以将有些必要的数据进行缓存,就比如arr.length
这种属性,不需要每次判断都获取一下,从而优化我们的代码。
示例代码如下:
... 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 } }) ...
代码运行结果如下:
正序 x 1,322,889 ops/sec ±1.36% (86 runs sampled)
缓存 x 1,356,696 ops/sec ±0.70% (92 runs sampled)
缓存的另一种写法 x 1,383,091 ops/sec ±0.70% (93 runs sampled)
最快的是:缓存的另一种写法
我们现在常用的循环有forEach
、for
和for...in
Zuerst müssen wir Abhängigkeiten im Projekt installieren. Der Code lautet wie folgt:
... suite .add('forEach', () => { let arr = new Array(100) let str = '' arr.forEach(i => { str += i }) }) .add('for...in', () => { let arr = new Array(100) let str = '' for (i in arr) { str += i } }) .add('for', () => { let arr = new Array(100) let str = '' for (let i = 0, l = arr.length; i < l; i++) { str += i } }) ...
... /*** 接收两类文件,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) }) ...
🎜// join1000 x 146.854 Operationen/Sek. ±1,86 % (88 Läufe abgetastet)🎜In den Ergebnissen stellt
// join10000 x 16.083 Operationen/Sek. ±1,06 % (92 Läufe abgetastet)
// Das schnellste ist: join1000🎜
ops/sec
die Anzahl der Ausführungen pro Sekunde dar. Je größer, desto besser, gefolgt von der prozentualen Differenz zwischen der oberen und unteren Anzahl der Ausführungen pro Sekunde Schließlich stellt der Inhalt in Klammern die Gesamtzahl der Stichproben dar. Wir können sehen, dass die Leistung von join1000
besser ist (ich habe das Gefühl, dass ich Unsinn rede). 🎜🎜Globale Variablen mit Vorsicht verwenden🎜🎜🎜Die hier genannten globalen Variablen sollten mit Vorsicht verwendet werden. Warum sollten sie mit Vorsicht verwendet werden? Die Hauptpunkte sind wie folgt: 🎜🎜... 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() }) ...
🎜Globale Variable x 158.697 Operationen/Sek. ±1,05 % (87 Läufe abgetastet)🎜Obwohl der Unterschied nicht groß ist, können wir das Gefühl haben, dass die Leistung globaler Variablen schlechter ist als die lokaler Variablen. 🎜🎜Methoden über den Prototyp hinzufügen🎜🎜Wenn Sie Methoden hinzufügen, die für Instanzobjekte zum Konstruktor erforderlich sind, versuchen Sie, sie mithilfe des Prototyps hinzuzufügen, anstatt sie innerhalb des Konstruktors hinzuzufügen. Wir können uns den folgenden Testcode ansehen: 🎜
Lokale Variable x 160.697 Operationen/Sek. ±1,03 % (90 Läufe abgetastet)
Die schnellste ist: lokale Variable 🎜
... 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() }) ...
🎜Constructor fügt intern x 573.786 Operationen/Sek. ±1,97 % hinzu (89 Läufe abgetastet)🎜 innerhalb des Konstruktors hinzu, um Speicherverluste bei Abschlüssen zu vermeiden 🎜🎜 Da Abschlüsse dazu führen, dass die Variablen in der Funktion im Speicher gespeichert werden, ist der Speicherverbrauch sehr groß, daher Abschlüsse kann nicht missbraucht werden. Andernfalls kann es zu Leistungsproblemen auf der Webseite und möglicherweise sogar zu Speicherverlusten kommen. Die Lösung besteht darin, vor dem Beenden der Funktion alle nicht verwendeten lokalen Variablen zu löschen (d. h. die lokalen Variablen
Prototypenmethode fügt intern x 581.693 Operationen/Sek. ±3,46 % hinzu (80 Läufe abgetastet)
Am meisten Die schnelle Sache ist: Fügen Sie 🎜
null
neu zuzuweisen). 🎜🎜Vermeiden Sie die Verwendung von Eigenschaftenzugriffsmethoden🎜🎜Vermeiden Sie bei Objekten in JavaScript die Verwendung einiger Eigenschaftenzugriffsmethoden. Dies liegt daran, dass alle Eigenschaften in JavaScript extern sichtbar sind. 🔜 >Nicht die Attributzugriffsmethode verwenden x 554.169 Operationen/Sek. ±2,03 % (85 Läufe abgetastet)arr.length
einfügen, die nicht bei jeder Beurteilung abgerufen werden müssen, wodurch unser Code optimiert wird. 🎜🎜🎜Der Beispielcode lautet wie folgt: 🎜🎜... suite .add('before', () => { var str = new String('string') }) .add('after', () => { var str = 'string' }) ...
🎜Vorwärtssequenz x 1.322.889 Operationen/Sek. ±1,36 % (86 Läufe abgetastet)
Cache x 1.356.696 Operationen/Sek. ±0,70 % (92 Läufe abgetastet)
Eine andere Art, Cache zu schreiben >🎜 Wählen Sie die optimale Schleifenmethode🎜🎜Zu den Schleifen, die wir jetzt häufig verwenden, gehörenforEach
-,for
- undfor...in
-Schleifen Gibt es diese Typen? Der Testcode lautet wie folgt: 🎜rrreee🎜🎜Die Code-Ausführungsergebnisse sind wie folgt: 🎜🎜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) }) ...Nach dem Login kopierenNach dem Login kopieren代码运行结果如下:
嵌套写法 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() }) ...Nach dem Login kopierenNach dem Login kopieren代码运行结果如下:
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() }) ...Nach dem Login kopierenNach dem Login kopieren代码运行结果如下:
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' }) ...Nach dem Login kopierenNach dem Login kopieren代码运行结果如下:
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前端】
Das obige ist der detaillierte Inhalt vonZusammenfassung und Weitergabe von 10 Tipps zur JavaScript-Codeoptimierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!