20個JS優化代碼技巧


原文網址鏈接為:http://www.jstips.co/ 。截取了一部分本人認為比較實用的技巧分享給大家。其中一小部分技巧為JS面向對象的寫法,不宜一一列出。關於JS面向對象的寫法可參考本人前幾篇隨筆:

JS面向對象(1) -- 簡介,入門,系統常用類,自定義類,constructor,typeof,instanceof,對象在內存中的表現形式

JS面向對象(2) -- this的使用,對象之間的賦值,for...in語句,delete使用,成員方法,json對象的使用,prototype的使用,原型繼承與原型鏈

JS面向對象(3) -- Object類,靜態屬性,閉包,私有屬性, call和apply的使用,繼承的三種實現方法

 

1.Insert item inside an Array(向數組中插入元素)

向一個數組中插入元素是平時很常見的一件事情。你可以使用push在數組尾部插入元素,可以用unshift在數組頭部插入元素,也可以用splice在數組中間插入元素。

 1  var arr = [1,2,3,4,5];
 2  //old method
 3  arr.push(6); 4 //new method 快43% 5 arr[arr.length] = 6; 6 7 var arr = [1,2,3,4,5]; 8 //old method 9 arr.unshift(0); 10 //new method 快98% 11 [0].concat(arr);

 

2.Improve Nested Conditionals(優化嵌套的條件語句) 

面對大量的if-else語句

 1  //method1
 2      if (color) {
 3          if (color === 'black') { 4  printBlackBackground(); 5 } else if (color === 'red') { 6  printRedBackground(); 7 } else if (color === 'blue') { 8  printBlueBackground(); 9 } else if (color === 'green') { 10  printGreenBackground(); 11 } else { 12  printYellowBackground(); 13  } 14  } 15 16 //method2 17 switch(color) { 18 case 'black': 19  printBlackBackground(); 20 break; 21 case 'red': 22  printRedBackground(); 23 break; 24 case 'blue': 25  printBlueBackground(); 26 break; 27 case 'green': 28  printGreenBackground(); 29 break; 30 default: 31  printYellowBackground(); 32  } 33 34 //method3 35 switch(true) { 36 case (typeof color === 'string' && color === 'black'): 37  printBlackBackground(); 38 break; 39 case (typeof color === 'string' && color === 'red'): 40  printRedBackground(); 41 break; 42 case (typeof color === 'string' && color === 'blue'): 43  printBlueBackground(); 44 break; 45 case (typeof color === 'string' && color === 'green'): 46  printGreenBackground(); 47 break; 48 case (typeof color === 'string' && color === 'yellow'): 49  printYellowBackground(); 50 break; 51  } 52 53 //method4 54 var colorObj = { 55 'black': printBlackBackground, 56 'red': printRedBackground, 57 'blue': printBlueBackground, 58 'green': printGreenBackground, 59 'yellow': printYellowBackground 60  }; 61 if (color in colorObj) { 62  colorObj[color](); 63 }

 

3.Sorting strings with accented characters(排列含音節字母的字符串)

Javascript有一個原生方法sort可以排列數組。一次簡單的array.sort()將每一個數組元素視為字符串並按照字母表排列。但是當你試圖整理一個非ASCII元素的數組時,你可能會得到一個奇怪的結果。

 1      ['Shanghai', 'New York', 'Mumbai', 'Buenos Aires'].sort();
 2      // ["Buenos Aires", "Mumbai", "New York", "Shanghai"]
 3      
 4  //method1
 5      // 西班牙語
 6      ['único','árbol', 'cosas', 'fútbol'].sort(); 7 // ["cosas", "fútbol", "árbol", "único"] // bad order 8 // 德語 9 ['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(); 10 // ["Wann", "Woche", "wäre", "wöchentlich"] // bad order 11 12 //method2 13 ['único','árbol', 'cosas', 'fútbol'].sort(Intl.Collator().compare); 14 // ["árbol", "cosas", "fútbol", "único"] 15 16 ['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(Intl.Collator().compare); 17 // ["Wann", "wäre", "Woche", "wöchentlich"]

 

4.Differences between undefined and null(undefined與null的區別

  • undefined表示一個變量沒有被聲明,或者被聲明了但沒有被賦值

  • null是一個表示“沒有值”的值

  • Javascript將未賦值的變量默認值設為undefined

  • Javascript從來不會將變量設為null。它是用來讓程序員表明某個用var聲明的變量時沒有值的。

  • undefined不是一個有效的JSON,而null

  • undefined的類型(typeof)是undefined

  • null的類型(typeof)是object

  • 它們都是基本類型

  • null === undefined // false

 

5.Check if a property is in a Object(檢查某對象是否有某屬性)

 1  //method1
 2      var myObject = {
 3        name: '@tips_js'
 4  }; 5 if (myObject.name) { } 6 7 //method2 8 var myObject = { 9 name: '@tips_js' 10  }; 11 12 myObject.hasOwnProperty('name'); // true 13 'name' in myObject; // true 14 15 myObject.hasOwnProperty('valueOf'); // false, valueOf 繼承自原型鏈 16 'valueOf' in myObject; // true

兩者檢查屬性的深度不同,換言之hasOwnProperty只在本身有此屬性時返回true,而in操作符不區分屬性來自於本身或繼承自原型鏈。

 

6.Tip to measure performance of a javascript block(測量javascript代碼塊性能的小知識)

快速的測量javascript的性能,我們可以使用console的方法,例如 

1  console.time("Array initialize");
2  var arr = new Array(100), 3 len = arr.length, 4  i; 5 6 for (i = 0; i < len; i++) { 7 arr[i] = new Object(); 8  }; 9 console.timeEnd("Array initialize"); // 0.711ms

 

7.Fat Arrow Functions(箭頭函數)

語法: 更少的代碼行; 不再需要一遍一遍的打function

語義: 從上下文中捕獲this關鍵字

 1  // 使用functions
 2  var arr = [5,3,2,9,1];
 3  var arrFunc = arr.map(function(x) { 4 return x * x; 5  }); 6  console.log(arrFunc ) 7 8 // 使用箭頭函數 9 var arr = [5,3,2,9,1]; 10 var arrFunc = arr.map((x) => x*x); 11 console.log(arrFunc )

箭頭函數在這種情況下省去了寫小括號,function以及return的時間。

 

8.Even simpler way of using indexOf as a contains clause(更簡單的使用indexOf實現contains功能)

JavaScript並未提供contains方法。檢測子字符串是否存在於字符串或者變量是否存在於數組你可能會這樣做。

1  var someText = 'javascript rules';
2  if (someText.indexOf('javascript') !== -1) { 3  } 4 5 // or 6 if (someText.indexOf('javascript') >= 0) { 7 }

建議的方法:

1  var someText = 'text';
2  !!~someText.indexOf('tex'); // someText contains "tex" - true
3  !~someText.indexOf('tex'); // someText NOT contains "tex" - false
4  ~someText.indexOf('asd'); // someText doesn't contain "asd" - false
5  ~someText.indexOf('ext'); // someText contains "ext" - true

 

9.Rounding the fast way(更快的取整)

一個位操作符 ~ 將輸入的32位的數字(input)轉換為 -(input+1). 兩個位操作符將輸入(input)轉變為 -(-(input + 1)+1) 是一個使結果趨向於0的取整好工具. 對於數字, 負數就像使用Math.ceil()方法而正數就像使用Math.floor()方法. 轉換失敗時,返回0,這在Math.floor()方法轉換失敗返回NaN時或許會派上用場。

 1  // 單個 ~
 2  console.log(~1337)    // -1338
 3  
 4  // 數字輸入
 5  console.log(~~47.11)  // -> 47
 6  console.log(~~-12.88) // -> -12
 7  console.log(~~1.9999) // -> 1
 8  console.log(~~3)      // -> 3
 9  
10  // 轉換失敗
11  console.log(~~[]) // -> 0
12  console.log(~~NaN)  // -> 0
13  console.log(~~null) // -> 0
14  
15  // 大於32位整數時轉換失敗
16  console.log(~~(2147483647 + 1) === (2147483647 + 1)) // -> 0

 

10.Safe string concatenation

 1  //method 1
 2  var one = 1;
 3  var two = 2; 4 var three = '3'; 5 var result = ''.concat(one, two, three); //"123" 6 //method 2 7 var one = 1; 8 var two = 2; 9 var three = '3'; 10 var result = one + two + three; //"33" instead of "123"

拼接時使用加號,可能會導致意想不到的錯誤結果。

 

11.Return objects to enable chaining of functions(返回對象,使方法可以鏈式調用)

 1  function Person(name) {
 2    this.name = name; 3 4 this.sayName = function() { 5 console.log("Hello my name is: ", this.name); 6 return this; 7  }; 8 9 this.changeName = function(name) { 10 this.name = name; 11 return this; 12  }; 13  } 14 15 var person = new Person("John"); 16 person.sayName().changeName("Timmy").sayName();

 在面向對象的Javascript中為對象建立一個方法時,返回當前對象可以讓你在一條鏈上調用方法。

 

12.Converting to number fast way(轉換為數字的更快方法)

將字符串轉換為數字是極為常見的。最簡單和快速的方法是使用+(加號) 來實現。

1  var one = '1';
2  var numberOne = +one; // Number 1
3  var one = '1'; 4 var negativeNumberOne = -one; // Number -1

  

13.Use === instead of ==(使用 === 而不是 ==)

== (或者 !=) 操作在需要的情況下自動進行了類型轉換。=== (或 !==)操作不會執行任何轉換。===在比較值和類型時,可以說比==更快。

 1  [10] ==  10      // 為 true
 2  [10] === 10      // 為 false
 3  
 4  '10' ==  10      // 為 true
 5  '10' === 10      // 為 false
 6  
 7   []  ==  0       // 為 true
 8   []  === 0       // 為 false
 9  
10   ''  ==  false   // 為 true 但 true == "a" 為false
11   ''  === false   // 為 false 

 

14.Filtering and Sorting a List of Strings(過濾並排序字符串列表)

你可能有一個很多名字組成的列表,需要過濾掉重復的名字並按字母表將其排序。

1  var keywords = ['do', 'if', 'in', 'for', 'new', 'try', 'var', 'case', 'else', 'enum', 'null', 'this', 'true', 'void', 'with', 'break', 'catch', 'class', 'const', 'false', 'super', 'throw', 'while', 'delete', 'export', 'import', 'return', 'switch', 'typeof', 'default', 'extends', 'finally', 'continue', 'debugger', 'function', 'do', 'if', 'in', 'for', 'int', 'new', 'try', 'var', 'byte', 'case', 'char', 'else', 'enum', 'goto', 'long', 'null', 'this', 'true', 'void', 'with', 'break', 'catch', 'class', 'const', 'false', 'final', 'float', 'short', 'super', 'throw', 'while', 'delete', 'double', 'export', 'import', 'native', 'public', 'return', 'static', 'switch', 'throws', 'typeof', 'boolean', 'default', 'extends', 'finally', 'package', 'private', 'abstract', 'continue', 'debugger', 'function', 'volatile', 'interface', 'protected', 'transient', 'implements', 'instanceof', 'synchronized', 'do', 'if', 'in', 'for', 'let', 'new', 'try', 'var', 'case', 'else', 'enum', 'eval', 'null', 'this', 'true', 'void', 'with', 'break', 'catch', 'class', 'const', 'false', 'super', 'throw', 'while', 'yield', 'delete', 'export', 'import', 'public', 'return', 'static', 'switch', 'typeof', 'default', 'extends', 'finally', 'package', 'private', 'continue', 'debugger', 'function', 'arguments', 'interface', 'protected', 'implements', 'instanceof', 'do', 'if', 'in', 'for', 'let', 'new', 'try', 'var', 'case', 'else', 'enum', 'eval', 'null', 'this', 'true', 'void', 'with', 'await', 'break', 'catch', 'class', 'const', 'false', 'super', 'throw', 'while', 'yield', 'delete', 'export', 'import', 'public', 'return', 'static', 'switch', 'typeof', 'default', 'extends', 'finally', 'package', 'private', 'continue', 'debugger', 'function', 'arguments', 'interface', 'protected', 'implements', 'instanceof'];
2  var filteredAndSortedKeywords = keywords 3 .filter(function (keyword, index) { 4 return keywords.lastIndexOf(keyword) === index; 5  }) 6 .sort(function (a, b) { 7 return a < b ? -1 : 1; 8 });

 因為我們不想改變我們的原始列表,所以我們准備用高階函數叫做filter,它將基於我們傳遞的回調方法返回一個新的過濾后的數組。回調方法將比較當前關鍵字在原始列表里的索引和新列表中的索引,僅當索引匹配時將當前關鍵字push到新數組。

最后我們准備使用sort方法排序過濾后的列表,sort只接受一個比較方法作為參數,並返回按字母表排序后的列表。

1  const filteredAndSortedKeywords = keywords
2   .filter((keyword, index) => keywords.lastIndexOf(keyword) === index) 3 .sort((a, b) => a < b ? -1 : 1); 4  console.log(filteredAndSortedKeywords); 5 // ['abstract', 'arguments', 'await', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'double', 'else', 'enum', 'eval', 'export', 'extends', 'false', 'final', 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements', 'import', 'in', 'instanceof', 'int', 'interface', 'let', 'long', 'native', 'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'short', 'static', 'super', 'switch', 'synchronized', 'this', 'throw', 'throws', 'transient', 'true', 'try', 'typeof', 'var', 'void', 'volatile', 'while', 'with', 'yield']

 

15.Short circuit evaluation in JS(JS中的短路求值)

短路求值是說, 只有當第一個運算數的值無法確定邏輯運算的結果時,才對第二個運算數進行求值:當AND(&&)的第一個運算數的值為false時,其結果必定為false;當OR(||)的第一個運算數為true時,最后結果必定為true。

邏輯或可以用來給參數設置默認值。

1  function theSameOldFoo(name){
2      name = name || 'Bar' ; 3 console.log("My best friend's name is " + name); 4  } 5 theSameOldFoo(); // My best friend's name is Bar 6 theSameOldFoo('Bhaskar'); // My best friend's name is Bhaskar

 邏輯與可以用來避免調用undefined參數的屬性時報錯

 1  var dog = {
 2    bark: function(){ 3 console.log('Woof Woof'); 4  } 5  }; 6 // 調用 dog.bark(); 7 dog.bark(); // Woof Woof. 8 // 但是當dog未定義時,dog.bark() 將會拋出"Cannot read property 'bark' of undefined." 錯誤 9 // 防止這種情況,我們可以使用 &&. 10 dog&&dog.bark(); // This will only call dog.bark(), if dog is defined.

 

16.!!(!!)

 1  !!"" // false
 2  !!0 // false
 3  !!null // false
 4  !!undefined // false
 5  !!NaN // false
 6  
 7  !!"hello" // true
 8  !!1 // true
 9  !!{} // true
10  !![] // true

 

17.Avoid modifying or passing arguments into other functions — it kills optimization(避免修改和傳遞arguments給其他方法 — 影響優化)

在JavaScript的方法里,arguments參數可以讓你訪問傳遞給該方法的所有參數。arguments是一個類數組對象;arguments可是使用數組標記訪問,而且它有length參數,但是它沒有filter, map, forEach這樣內建到數組內的方法。因此,如下代碼是一個非常常見的將arguments轉換為數組的辦法:

1 var args = Array.prototype.slice.call(arguments);
2 //或者
3 var args = [].slice.call(arguments);

不幸的是,傳遞arguments給任何參數,將導致Chrome和Node中使用的V8引擎跳過對其的優化,這也將使性能相當慢。所以,正確的做法只有:

1 var args = new Array(arguments.length);
2     for(var i = 0; i < args.length; ++i) { 3 args[i] = arguments[i]; 4 }

 

18.Implementing asynchronous loop(實現異步循環)

試着寫一個異步方法,每秒打印一次循環的索引值。

1 for (var i=0; i<5; i++) {
2     setTimeout(function(){ 3  console.log(i); 4 }, 1000); 5 } 

但輸出的結果會是5,5,5,5,5。這明顯是有問題的,原因是:每次時間結束(timeout)都指向原始的i,而並非它的拷貝。所以,for循環使i增長到5,之后timeout運行並調用了當前i的值(也就是5)。

解決的辦法是:有幾個不同的方式可以拷貝i。最普通且常用方法是通過聲明函數來建立一個閉包,並將i傳給此函數。我們這里使用了自調用函數。

1 for (var i=0; i<5; i++) {
2     (function(num){ 3 setTimeout(function(){ 4  console.log(num); 5 }, 1000); 6  })(i); 7 } 

 

19.Flattening multidimensional Arrays in JavaScript(Javascript多維數組扁平化)

測試地址:http://jsperf.com/flatten-an-array-loop-vs-reduce/6

 

 

20.Using JSON.Stringify(使用JSON.Stringify)

加入有一個對象具有參數"prop1", "prop2", "prop3"。 我們可以通過傳遞 附加參數 給 JSON.stringify 來選擇性將參數生成字符串,像這樣:

 1 var obj = {
 2     'prop1': 'value1', 3 'prop2': 'value2', 4 'prop3': 'value3' 5 }; 6 7 var selectedProperties = ['prop1', 'prop2']; 8 9 var str = JSON.stringify(obj, selectedProperties); 10 11 // str 12 // {"prop1":"value1","prop2":"value2"}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM