JavaScript技巧

  1. 轉化爲Boolean類型 
    所有JavaScript中的值都能隱式的轉化爲Boolean類型,比如:
    [js] view plain copy
    1. 0 == false// true<br>  
    2. 1 == true// true<br>  
    3. '' == false // true<br>  
    4. null == false // true<br>  
    但是這些值都不是Boolean類型。
    因此當我們使用三個等於號進行比較時:
    [js] view plain copy
    1. 0 === false// false<br>  
    2. 1 === true// false<br>  
    3. '' === false // false<br>  
    4. null === false // false<br>  
    現在的問題是如何將其他類型轉化爲Boolean類型:
    [js] view plain copy
    1. !!0 === false// true<br>  
    2. !!1 === true// true<br>  
    3. !!'' === false // true<br>  
    4. !!null === false // true<br>  

  2. 爲參數賦初值 
    JavaScript中沒有重載的概念,但是JavaScript中函數的參數都是可選的,如果調用時少寫了一個參數,將會被undefined 所代替。
    [js] view plain copy
    1. function plus(base, added) {<br>  
    2.     return base + added;<br>  
    3. }<br>  
    4. plus(2); // NaN<br>  
    在這個例子中,plus(2) 和plus(2, undefined) 是等價的,2 + undefined 的結果是NaN 。 
    現在的問題是,如果沒有傳遞第二個參數,如何爲它賦初值呢?
    [js] view plain copy
    1. function plus(base, added) {<br>  
    2.     added = added || 1;<br>  
    3.     return base + added;<br>  
    4. }<br>  
    5. plus(2); // 3<br>  
    6. plus(2, 2); // 4<br>  


    有網友提到 plus(2, 0) = 3; 的確是這樣的,看來這個地方還要做一些特殊處理:
    [js] view plain copy
    1. function plus(base, added) {<br>  
    2.     added = added || (added === 0 ? 0 : 1);<br>  
    3.     return base + added;<br>  
    4. }<br>  

  3. 阻止別人在Iframe中加載你的頁面 
    如果你的網站變得非常有人氣的時候,就有很多網站想鏈接到你的網站,甚至想把你的網頁通過IFrame嵌入它自己的網頁。 
    這樣就不好玩了,那麼如何來阻止這樣行爲呢?
    [js] view plain copy
    1. if(top !== window) {<br>  
    2.  top.location.href = window.location.href;<br>  
    3. }<br>  
    這段代碼應該放在你每個頁面的head 中,如果你想知道現實中有沒人在用,看看baidu的博客你就知道了。 

  4. 字符串替換 
    String.prototype.replace 函數經常會讓那些非常熟悉C#或者Java的程序員感到迷惑。 
    比如:
    [js] view plain copy
    1. 'Hello world, hello world'.replace('world''JavaScript');<br>  
    2. // The result is "Hello JavaScript, hello world"<br>  
    replace 函數的第一個參數是正則表達式。
    如果你傳遞一個字符串到第一個參數,則只有第一個找到的匹配字符串被替換。 
    爲了解決這個問題,我們可以使用正則表達式:
    [js] view plain copy
    1. 'Hello world, hello world'.replace(/world/g, 'JavaScript');<br>  
    2. // The result is "Hello JavaScript, hello JavaScript"<br>  
    我們還可以指定在替換時忽略大小寫:
    [js] view plain copy
    1. 'Hello world, hello world'.replace(/hello/gi, 'Hi');<br>  
    2. // The result is "Hi world, Hi world"<br>  

  5. 將arguments轉化爲數組 
    函數中的預定義變量arguments 並非一個真正的數組,而是一個類似數組的對象。 
    它具有length 屬性,但是沒有slice, push, sort等函數,那麼如何使arguments 具有這些數組纔有的函數呢? 
    也就是說如何使arguments 變成一個真正的數組呢?
    [js] view plain copy
    1. function args() {<br>  
    2.     return [].slice.call(arguments, 0);<br>  
    3. }<br>  
    4. args(2, 5, 8); // [2, 5, 8]<br>  

  6. 爲parseInt函數指定第二個參數 
    parseInt 用來將字符串轉化爲整形的數字,語法爲:
    [js] view plain copy
    1. parseInt(str, [radix])<br>  
    其中第二個參數是可選的,用來指定第一個參數是幾進制的。 
    如果沒有傳遞第二個參數,則按照如下規則:
    ->如果str 以 0x 開頭,則認爲是16進制。
    ->如果str 以 0 開頭,則認爲是8進制。
    ->否則,認爲是10進制。
    因此如下的代碼將會讓人很迷惑,如果你不知道這些規則:
    [js] view plain copy
    1. parseInt('08'); // 0<br>  
    2. parseInt('08', 10); // 8<br>  

    所以,安全起見一定要爲parseInt 指定第二個參數。 
  7. 從數組中刪除一個元素 
    或許我們可以通過delete 來做到:
    [js] view plain copy
    1. var arr = [1, 2, 3, 4, 5];<br>  
    2. delete arr[1];<br>  
    3. arr; // [1, undefined, 3, 4, 5]<br>  
    可以看到,delete 並不能真正的刪除數組中的一個元素。刪除的元素會被undefined 取代,數組的長度並沒有變化。 

    事實上,我們可以通過Array.prototype中的splice 函數來刪除數組中的元素,如下所示:
    [js] view plain copy
    1. var arr = [1, 2, 3, 4, 5];<br>  
    2. arr.splice(1, 1);<br>  
    3. arr; // [1, 3, 4, 5]<br>  

  8. 函數也是對象 
    在JavaScript中函數也是對象,因爲我們可以爲函數添加屬性。 
    比如:
    [js] view plain copy
    1. function add() {<br>  
    2.     return add.count++;<br>  
    3. }<br>  
    4. add.count = 0;<br>  
    5. add();    // 0<br>  
    6. add();    // 1<br>  
    7. add();    // 2<br>  
    我們爲函數add 添加了count 屬性,用來記錄此函數被調用的次數。 

    當然這可以通過更優雅的方式來實現:
    [js] view plain copy
    1. function add() {<br>  
    2.     if(!arguments.callee.count) {<br>  
    3.         arguments.callee.count = 0;<br>  
    4.     }<br>  
    5.     return arguments.callee.count++;<br>  
    6. }<br>  
    7. add();    // 0<br>  
    8. add();    // 1<br>  
    9. add();    // 2<br>  
    arguments.callee 指向當前正在運行的函數。 

  9. 數組中的最大值 
    如何在全是數字的數組中找到最大值,我們可以簡單的通過循環來完成:
    [js] view plain copy
    1. var arr = [2, 3, 45, 12, 8];<br>  
    2. var max = arr[0];<br>  
    3. for(var i in arr) {<br>  
    4.     if(arr[i] > max) {<br>  
    5.         max = arr[i];<br>  
    6.     }<br>  
    7. }<br>  
    8. max; // 45<br>  
    有沒有其他方法?我們都知道JavaScript中有一個Math 對象進行數字的處理:
    [js] view plain copy
    1. Math.max(2, 3, 45, 12, 8); // 45<br>  
    然後,我們可以這樣來找到數組中最大值:
    [js] view plain copy
    1. var arr = [2, 3, 45, 12, 8];<br>  
    2. Math.max.apply(null, arr); // 45<br>  

  10. 爲IE添加console.log 函數 
    在Firefox下並有Firebug的支持下,我們經常使用console.log 來在控制檯記錄一些信息。 
    但是這種做法在IE下會阻止JavaScript的執行(在Firefox下沒有啓用Firebug情況下也是一樣),因爲此時根本沒有console 對象存在。 
    我們可以通過如下小技巧來防止這樣情況的發生:
    [js] view plain copy
    1. if (typeof(console) === 'undefined') {<br>  
    2.     window.console = {<br>  
    3.         log: function(msg) {<br>  
    4.             alert(msg);<br>  
    5.         }<br>  
    6.     };<br>  
    7. }<br>  
    8. console.log('debug info.');<br>  

  11. undefined 是JavaScript中保留關鍵字麼? 
    看起來像是的,但實際上undefined並不是JavaScript中的關鍵字:
    [js] view plain copy
    1. var undefined = 'Hello';   <br>  
    2. undefined; // 'Hello'<br>  
    這段代碼可能會讓你感到很奇怪,不過它的確能夠正常運行,undefined 只是JavaScript中一個預定義的變量而已。 
    注:在JavaScript程序中,千萬不要這樣做,這個技巧只是告訴你有這麼一回事而已。 

  12. 判斷一個變量是否爲undefined 
    兩種情況下,一個變量爲undefined: 
    1. 聲明瞭變量,但是沒有賦值
    [js] view plain copy
    1. var name;   <br>  
    2. name === undefined; // true<br>  
    2. 從來沒有聲明過此變量
    [js] view plain copy
    1. name2 === undefined; // error – name2 is not defined<br>  
    在第二種情況下,會有一個錯誤被拋出,那麼如果判斷一個變量是否爲undefined而不產生錯誤呢? 
    下面提供了一種通用的方法:
    [js] view plain copy
    1. typeof(name2) === ‘undefined’; // true<br>  

  13. 預加載圖片 
    預加載圖片就是加載頁面上不存在的圖片,以便以後使用JavaScript把它們快速顯示出來。 
    比如你想在鼠標移動到某個圖片上時顯示另一張圖片:
    [js] view plain copy
    1. var img = new Image();   <br>  
    2. img.src = "clock2.gif";<br>  
    [xml] view plain copy
    1. <img src="clock.gif" mce_src="clock.gif" alt="" <br>  
    2.     onmouseover="this.src='clock2.gif';"   <br>  
    3.     onmouseout="this.src=clock.gif';" /><br>  

    那麼,如何加載一組圖片呢?考慮如下代碼:
    [js] view plain copy
    1. var source = ['img1.gif','img2.gif'];   <br>  
    2. var img = new Image();   <br>  
    3. for(var i = 0; i < source.length; i++) {   <br>  
    4.     img.src = source[i];   <br>  
    5. }<br>  
    實際上,這段代碼只能預加載最後的一張圖片,因爲其他的圖片根本沒有時間來預加載在循環到來的時候。 
    因此正確的寫法應該是:
    [js] view plain copy
    1. var source = ['img1.gif','img2.gif'];   <br>  
    2. for(var i = 0; i < source.length; i++) {   <br>  
    3.     var img = new Image();   <br>  
    4.     img.src = source[i];   <br>  
    5. }<br>  

  14. 閉包(closure) 
    閉包指的是函數內的局部變量,當函數返回時此變量依然可用。 
    當你在函數內部定義另外一個函數時,你就創建了一個閉包,一個著名的例子: 
    [js] view plain copy
    1. function add(i) {   <br>  
    2.     return function() {   <br>  
    3.         return ++i;   <br>  
    4.     };   <br>  
    5. }   <br>  
    6. add(2).toString(); // "function () { return ++i; }"   <br>  
    7. add(2)(); // 3<br>  
    add(2) 是一個函數,它可能獲取外部函數的局部變量i 。 
    參考文章 

  15. 私有變量 
    我們經常使用命名規範來標示一個變量是否爲私有變量(最常用來標示):
    [js] view plain copy
    1. var person = {   <br>  
    2.     _name: '',   <br>  
    3.     getName: function() {   <br>  
    4.         return this._name || 'not defined';   <br>  
    5.     }   <br>  
    6. };   <br>  
    7. person.getName(); // "not defined"<br>  
    下劃線前綴用來作爲私有變量的約定,但是其他開發人員仍然可以調用此私有變量:
    [js] view plain copy
    1. person._name; // ""<br>  
    那麼,如何在JavaScript中創建一個真正的私有變量呢? 
    主要技巧是使用匿名函數(anonymous function)和閉包(closure)。
    [js] view plain copy
    1. var person = {};   <br>  
    2. (function() {   <br>  
    3.     var _name = '';   <br>  
    4.     person.getName = function() {   <br>  
    5.         return _name || 'not defined';   <br>  
    6.     }   <br>  
    7. })();   <br>  
    8. <br>  
    9. person.getName(); // "not defined"   <br>  
    10. typeof(person._name); // "undefined"<br>  

  16. JavaScript沒有塊級上下文(Scope) 
    JavaScript中塊級代碼沒有上下文,實際上只有函數有自己的上下文。
    [js] view plain copy
    1. for(var i = 0; i < 2; i ++) { <br>  
    2. <br>  
    3. } <br>  
    4. i;  // 2<br>  
    如果想創建一個上下文,可以使用自執行的匿名函數:
    [js] view plain copy
    1. (function (){ <br>  
    2.     for(var i = 0; i < 2; i ++) { <br>  
    3.     <br>  
    4.     }<br>  
    5. })(); <br>  
    6. typeof(i) === 'undefined';  // true<br>  

  17. 怪異的NaN 
    NaN用來表示一個值不是數字。
    NaN在JavaScript中行爲很怪異,是因爲那NaN和任何值都不相等(包括它自己)。
    [js] view plain copy
    1. NaN === NaN; // false<br>  
    因爲下面的代碼可能會讓一些人抓狂:
    [js] view plain copy
    1. parseInt('hello', 10); // NaN <br>  
    2. parseInt('hello', 10) == NaN; // false <br>  
    3. parseInt('hello', 10) === NaN; // false<br>  
    那麼如何來檢查一個值是否NaN?
    可以使用window.isNaN來判斷:
    [js] view plain copy
    1. isNaN(parseInt('hello', 10)); // true<br>  

  18. 真值和假值 
    JavaScript中所有值都能隱式地轉化爲Boolean類型。
    在條件判斷中,下面這些值會自動轉化爲false:
    null, undefined, NaN, 0, ‘’, false 
    因此,不需要做如下複雜的判斷:
    [js] view plain copy
    1. if(obj === undefined || obj === null) { <br>  
    2. }<br>  
    而只需要這樣做就行了:
    [js] view plain copy
    1. if(!obj) { <br>  
    2. <br>  
    3. }<br>  

  19. 修改arguments 
    比如,添加一個值到arguments中:
    [js] view plain copy
    1. function add() { <br>  
    2.     arguments.push('new value'); <br>  
    3. } <br>  
    4. add(); // error - arguments.push is not a function<br>  
    這樣會出錯,因爲arguments 不是一個真正的數組,沒有push方法。 
    解決辦法:
    [js] view plain copy
    1. function add() { <br>  
    2.     Array.prototype.push.call(arguments, 'new value'); <br>  
    3.     return arguments; <br>  
    4. } <br>  
    5. add()[0]; // "new value"<br>  

  20. Boolean 和 new Boolean 
    我們可以把Boolean看做是一個函數,用來產生Boolean類型的值(Literal):
    [js] view plain copy
    1. Boolean(false) === false// true <br>  
    2. Boolean('') === false// true<br>  
    所以,Boolean(0) 和!!0 是等價的。 
    我們也可以把Boolean看做是一個構造函數,通過new 來創建一個Boolean類型的對象:
    [js] view plain copy
    1. new Boolean(false) === false// false <br>  
    2. new Boolean(false) == false// true <br>  
    3. typeof(new Boolean(false)); // "object" <br>  
    4. typeof(Boolean(false)); // "boolean"<br>  

  21. 快速字符串連接 
    我們經常使用+ 將較短的字符串連接爲一個長字符串,這在大部分的情況下是沒問題的。 
    但是如果有大量的字符串需要連接,這種做法將會遇到性能問題,尤其是在IE下。 
    [js] view plain copy
    1. var startTime = new Date();<br>  
    2. var str = '';<br>  
    3. for (var i = 0; i < 50000; i++) {<br>  
    4.     str += i;<br>  
    5. }<br>  
    6. alert(new Date() - startTime);  // Firefox - 18ms, IE7 - 2060ms<br>  
    [js] view plain copy
    1. var startTime = new Date();<br>  
    2. var arr = [];<br>  
    3. for (var i = 0; i < 100000; i++) {<br>  
    4.     arr.push(i);<br>  
    5. }<br>  
    6. var str = arr.join("");<br>  
    7. alert(new Date() - startTime); // Firefox - 38ms, IE7 - 280ms<br>  

    可以看到Firefox似乎對+ 操作符進行了優化,而IE則表現的傻乎乎的。 
  22. 一元操作符 +
    在JavaScript中,我們可以在字符串之前使用一元操作符“+”。這將會把字符串轉化爲數字,如果轉化失敗則返回NaN。
    [js] view plain copy
    1. 2 + '1'// "21"<br>  
    2. 2 + ( +'1'); // 3<br>  
    如果把 + 用在非字符串的前面,將按照如下順序進行嘗試轉化:
    1. 調用valueOf()
    2. 調用toString()
    3. 轉化爲數字
    [js] view plain copy
    1. +new Date; // 1242616452016<br>  
    2. +new Date === new Date().getTime(); // true<br>  
    3. +new Date() === Number(new Date) // true<br>  
    參考文章 

  23. encodeURI和encodeURIComponent 
    window.encodeURI函數用來編碼一個URL,但是不會對以下字符進行編碼:“:”, “/”, “;”, “?”. 
    window.encodeURIComponent則會對上述字符進行編碼。
    我們通過一個例子來說明:
    [js] view plain copy
    1. 'index.jsp?page='+encodeURI('/page/home.jsp');  // "index.jsp?page=/page/home.jsp"<br>  
    2. 'index.jsp?page='+encodeURIComponent('/page/home.jsp');  // "index.jsp?page=%2Fpage%2Fhome.jsp"<br>  
    因此,在對URL進行編碼時我們經常會選擇 encodeURIComponent。 

  24. table.innerHTML在IE下是隻讀屬性 
    我們經常通過節點的innerHTML 屬性來填充節點,比如:
    [xml] view plain copy
    1. <div id="container1"> </div><br>  
    [js] view plain copy
    1. document.getElementById('container1').innerHTML = "Hello World!";  
    但是在IE下設置table.innerHTML 將會導致錯誤:
    [xml] view plain copy
    1. <table id="table1"> </table><br>  
    2.               
    [js] view plain copy
    1. // works well in Firefox, but fail to work in IE<br>  
    2. document.getElementById('table1').innerHTML = "<tr><td>Hello</td><td>World!</td></tr>";<br>  
    實際上,table, thead, tr, select等元素的innerHTML屬性在IE下都是隻讀的。 

    那麼如果動態的創建一個table呢,下面提供了一種可行的方法:
    [xml] view plain copy
    1. <div id="table1"> </div><br>  
    2.                
    [js] view plain copy
    1. document.getElementById('table1').innerHTML = "<table><tr><td>Hello</td><td>World!</td></tr></table>";<br>  

  25. 0.1+0.2 != 0.3 
    JavaScript將小數作爲浮點數對待,所以可能會產生一些四捨五入的錯誤,比如:
    [js] view plain copy
    1. 0.1 + 0.2; // 0.30000000000000004  
    你可以通過toFixed方法指定四捨五入的小數位數:
    [js] view plain copy
    1. (0.1 + 0.2).toFixed(); // "0"<br>  
    2. (0.1 + 0.2).toFixed(1); // "0.3"<br>  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章