最近家裡雜事較多,自學時間實在少的可憐,所以都在空閑時間看看老外寫的內容,學習之外順便翻譯分享~等學習的時間充足些再寫寫自己的一些學習內容和知識點分析(最近有在接觸的:複習(C#,SQL)、(學習)TypeScript,(基礎操作)MongoDB。TypeScript之後入手AngularJs 2.
最近家裡雜事較多,自學時間實在少的可憐,所以都在空閑時間看看老外寫的內容,學習之外順便翻譯分享~等學習的時間充足些再寫寫自己的一些學習內容和知識點分析(最近有在接觸的:複習(C#,SQL)、(學習)TypeScript,(基礎操作)MongoDB。TypeScript之後入手AngularJs 2.0)
後續如有內容,本篇將會照常更新併排滿15個知識點,以下是其他幾篇譯文的地址:
第一篇地址:( 譯、持續更新 ) JavaScript 上分小技巧(一)
第二篇地址:( 譯、持續更新 ) JavaScript 上分小技巧(二)
#35 - 簡潔的代碼
對於我們懶惰的程式員來說,有時候打字都是浪費時間。所以,我們可以使用一些技巧來幫助我們,使我們的代碼更清潔和更簡單。
類似的使用:
x += 23; // x = x + 23; y -= 15; // y = y - 15; z *= 10; // z = z * 10; k /= 7; // k = k / 7; p %= 3; // p = p % 3; d **= 2; // d = d ** 2; m >>= 2; // m = m >> 2; n <<= 2; // n = n << 2; n ++; // n = n + 1; n --; // n = n - 1;
if-else(使用三元運算符)
這是我們平常的規範寫法:
var newValue; if(value > 10) newValue = 5; else newValue = 2;
我們可以使用三元運算符:
var newValue = (value > 10) ? 5 : 2;
null,undefined,空值檢查
if (variable1 !== null || variable1 !== undefined || variable1 !== '') { var variable2 = variable1; }
簡短的寫法:
var variable2 = variable1 || '';
註:如果variable1是一個數,將會先檢查它是否為0。
數組/對象的表示方法
數組:
var a = new Array(); a[0] = "myString1"; a[1] = "myString2";
我們用下麵的代碼代替上面的代碼:
var a = ["myString1", "myString2"];
對象:
var skillSet = new Array(); skillSet['Document language'] = 'HTML5'; skillSet['Styling language'] = 'CSS3';
我們使用下麵的代碼代替上面的代碼:
var skillSet = { 'Document language' : 'HTML5', 'Styling language' : 'CSS3' };
#34 - 執行非同步調用的迴圈
讓我們試著寫一個非同步函數,它每秒列印一次迴圈的索引值。
for (var i=0; i<5; i++) { setTimeout(function(){ console.log(i); }, 1000); }
以上程式將會輸出:
_> 5 _> 5 _> 5 _> 5 _> 5
所以,它根本沒有正確的執行。
原因:
因為timeout的非同步,而每次的timeout指向的是原始的i,不是副本中的。所以迴圈直到i=5,然後timeout運行,並且列印當前的i(5)。
好吧,這個問題似乎很容易。一個馬上就可以解決的方案是即可將當前的i值當作一個臨時變數緩存在迴圈中。
for (var i=0; i<5; i++) { var temp = i; setTimeout(function(){ console.log(i); }, 1000); }
但是上面的程式輸出的還是:
_> 5 _> 5 _> 5 _> 5 _> 5
所以,那也行不通,因為代碼塊不會創建一個作用域並且變數的初始化被提升到作用域的前面。事實上,和之前的代碼是一樣的:
解決方案:
有很多種不同的方案來複制i。最常見的是創建一個閉包,通過聲明一個函數,並將i作為參數傳入。在這裡,我們用自執行函數:
for (var i=0; i<5; i++) { (function(num){ setTimeout(function(){ console.log(num); }, 1000); })(i); }
在JavaScript中,參數是按值傳遞給函數。像數字、日期和字元串的原始類型基本上是複製的。如果你在函數內改變了它們,不影響它在外部範圍的值。對象是特殊的:如果內部函數改變了它的一個屬性,則在所有作用域中的對應值跟著變化。
#33 - 使用一行代碼簡單的創建一個[1,...,N]的範圍數組
下麵這行代碼能夠創建一個[1,...,N]的範圍數組
Array.apply(null,{length:N}).map(Fn,Context);
讓我們將這行代碼拆分成幾部分。我們都知道javascript的apply()函數的作用。在apply()里,第一個參數是根據第二個參數而來的上下文對象,它是被我們稱為apply()函數的參數列表。
function add(a, b){ return (a+b); } add.apply(null,[5, 6]);
將會返回5+6的和。
javascript中的數組的map()函數有2個參數,第一個是回調函數,第二個是回調函數的上下文對象。回調函數有3個參數:value(值)、index(索引)、我們處理的整個陣列。所以普通語法是:
[1, 2, 3].map(function(value, index, arr){ //Code }, this);
下麵的這行代碼創建一個給定長度的數組:
Array.apply(null,{length:N});
把所有部分放到一起就是解決方案:
Array.apply(null,{length:N}).map(Fn,Context);
如果你想創建一個[1,...,N]的範圍數組:
Array.apply(null, {length: N}).map(function(value, index){ return index+1; });
#32 - Map() 有秩序的給對象填加屬性
object是Object類型中的一個成員,它是個包含原始值、對象或者函數的一個無序的屬性集合。儲存在對象屬性中的函數被成為方法。ECMAScript
看以下代碼:
var myObject = { z: 1, '@': 2, b: 3, 1: 4, 5: 5 }; console.log(myObject) // Object {1: 4, 5: 5, z: 1, @: 2, b: 3} for (item in myObject) {... // 1 // 5 // z // @ // b
每個瀏覽器針對對象技術都有著各自的規則,所以秩序是不確定的。
怎麼解決這個問題呢?
Map
使用ES6中的一個新特性---Map。一個Map對象按插入的順序來迭代它的元素---for...of迴圈為每個迴圈項返回一個[key,value]形式的數組。
var myObject = new Map(); myObject.set('z', 1); myObject.set('@', 2); myObject.set('b', 3); for (var [key, value] of myObject) { console.log(key, value); ... // z 1 // @ 2 // b 3
舊瀏覽器的hack
Mozilla 建議:
因此,如果你想在一個交叉的瀏覽器環境中模擬一個有序的關聯數組,你不得不使用2個單獨的數組(一個鍵的數組和一個值的數組),或構建一個單屬性對象的數組等。
// 使用兩個數組 var objectKeys = [z, @, b, 1, 5]; for (item in myObject) { myObject[item] ... // 創建一個單屬性對象的數組 var myData = [{z: 1}, {'@': 2}, {b: 3}, {1: 4}, {5: 5}];
#31 - 避免將"arguments"進行修改或者傳遞到其他函數 - 這將扼殺優化
背景:
在javascript的函數中,名為arguments的變數讓你能夠操作傳入函數的所有參數。arguments是個類似數組的object,arguments能夠使用數組符號來做操作,並且有length屬性,但是它不能改使用一些數組內置的方法,比如filter、map和forEach。正是因為如此,將參數轉換為數組來使用是一種相當普遍的做法:
var args = Array.prototype.slice.call(arguments);
從Array的prototypr中調用slice方法,傳入arguments;slice方法返回一個新的淺度複製arguments的數組對象。這是一個常用的速記法:
var args = [].slice.call(arguments);
在這個案例中,我們更簡單的用一個字面量的空數組來代替從Array的prototype調用slice方法。
優化:
不幸的是,在基於Chrome和Node的JavaScript V8引擎上,在函數內將arguments傳入任何其他函數都會導致性能變慢。看這篇文章:優化殺手。將arguments傳遞給任何其他函數稱為參數泄露。
作為替代,如果想要可以使用的參數數組,你需要做這些:
var args = new Array(arguments.length); for(var i = 0; i < args.length; ++i) { args[i] = arguments[i]; }
這是更詳細的,但在生產代碼中,以這些來進行性能優化是值得的。
### 2016-02-04 更新 ###