我所瞭解的JavaScript糟粕和雞肋

靜逸發表於2015-07-08

糟粕

全域性變數

眾所周知,全域性變數在很小的程式中可能會帶來方便,但隨著程式變得越來大,全域性變數將難以處理,全域性變數將降低程式的可靠性。

在js中有3種方式定義全域性變數

脫離任何函式安排一個var語句   //var foo=value;

直接新增一個屬性到全域性物件上  //window.foo=value;

直接使用未經宣告的變更(其實這叫隱匿全域性變數)    //foo=value;  

 

作用域

 眾所周知,在JavaScript中沒有塊級作用域,而且在JavaScript有提升變數宣告的功能,所以最好的方式是在每個函式的開頭部分宣告所有變數。

自動插入分號

 JavaScript會試圖通過自動插入分號來修正有缺損的程式。

        return
        {
            status:true
        };

上面的程式碼大家自然的會想到會返回一個包含status成員元素的物件。但是由於JavaScript自動插入讓它變成了一個返回undefined。

所以把{放在上一行的尾部而不是下一行的頭部可避免上述問題

保留字

 當保留字被用作物件字面量的鍵值時,它們必須被引號括起來。它們不能被用在點表示法中,所以有時必須使用括號表示法。

最好不要用保留字做識別符號  JavaScript保留字如下圖片所列

Unicode

 在阮一峰的一篇博文Unicode與JavaScript詳解 中特別清楚說明了JavaScript的編碼。

簡述一點的說就是JavaScript的字元是16位的,所以在編碼方面很多字元表示出來都是很有困難的。

typeof

 typeof null返回的卻是object

 typeof /a/ 有一些會返回為object而其它的卻返回function

parseInt

 將一個字串轉換為整數,但是在遇到非數字時停止解析。

 如果該字串第一個字元是0,那麼該字串將會被基於八進位制而不是十進位制來求值。(但關鍵是在ie8以下的瀏覽器卻還是當成十進位制來求值)

 建議使用parseInt時最好提供基數引數,即使轉換的是十進位制。

+

 +主要用於加法運算或字串連線。但是隻要其中一個執行符為字串,則返回字串

 所以在你打算用+做加法運算時,請確保兩個運算數都是整數。

浮點數

 在JavaScript中,0.1+0.2卻不等於0.3

浮點數中的整數運算是精確的,所以小數表現出來的錯誤可以通過指定精度來避免。

NAN

 typeof不能辨別數字和NAN,並且事實證明NAN不等同於它自己

        function isNumber(value) {
            return typeof value === 'number' && isFinite(value);
        }

偽陣列

 在JavaScript是沒有真正的陣列的!在其它程式語言中,陣列都是按照數字進行索引的,但是JavaScript中事實上並沒有陣列,陣列和物件事實上並沒有多大的區別,JavaScript提供了一種類陣列特性的物件,它把陣列下標轉換為字串,用其作為屬性,屬性的檢查和更新的方式與物件一模一樣,除了有一個可以用整數作為屬性名的特性外。 

        //判斷是否為陣列
        function isArray(value) {
            return value &&
                    typeof value === 'object' &&
                    typeof value.length === 'number' &&
                    typeof value.splice === 'function' &&
                    !(value.propertyIsEnumerable('length'));
        };

 

假值

 在JavaScript中擁有一大堆假值,如下圖所示。undefined和NAN並不是常量,它們是全域性變數,而且你可以改變它們的值

hasOwnProperty

 大家都知道,hasOwnProperty方法被用途一個過濾器去避開for in語句,因為它只是一個方法,所以在任何物件中,它可能會被一個不同的函式甚至一個非函式的值所替換。

        var another = {};
        var name;
        another.hasOwnProperty = null; //這裡修改了hasOwnProperty方法為一個非函式值
        for (name in another) {
            if (another.hasOwnProperty(name)) {
                console.log(another[name]); //這裡使用hasOwnProperty結果就報錯  TypeError: object is not a function
            }
        }

雞肋

==

 永遠只使用===和!==。因為==預設會進行型別轉換,規則十分難記。至於規則詳情見我的另一篇文章 JS == 的轉換規則     

with

 大家都知道with改變作用域,在有些情況下是相當方便的,但帶來的效能問題卻是相當沉重的。建議最好不要使用with

eval

eval帶來的問題總結如下: 

  • 使得程式碼更加難以閱讀
  • 效能顯著降低
  • 不利於JSLint工具檢測問題
  • 降低了應用的安全性

類似於eval的還有1)Function構造器2)在setTimeout或setInterval函式中傳遞字串引數

像這樣的都儘量避免

continue語句

 這條命令的作用是返回到迴圈的頭部,但是迴圈本來就會返回到頭部。所以通過適當的構造,完全可以避免使用這條命令,使得效率得到改善。通過重構移除continue語句效能方面能得到顯著改善

switch貫穿

 大家都知道在js的switch語句中在一個case條件可以貫穿到另一個case中,雖然這種特性是在某些場景下是非常有用的,但是它們也是非常危險的。

缺少塊的語句

 建議即使只有一條語句,在if、while、do或for中還是用花括號把它們括起來

++   --

 當用++和--時,程式碼往往變得過於緊密和隱晦,所以作為一條原則建議不要使用它們

表面上可以讓程式碼變得很緊湊,但是實際上會讓程式碼看上去更復雜和更晦澀。因此為了程式碼的整潔性和易讀性,不用為好。

位操作符

 JavaScript沒有整數型別,只有雙精度的浮點數,因此位操作符將它們的數字運算先轉換成整數,接著執行運算然後再轉換回去,所以在JavaScript中,位操作符運算效率並不高,所以建議少使用它。

 

備註:

  • JavaScript中是沒有整型概念的,但利用好位操作符可以輕鬆處理,同時獲得效率上的提升。
  • |0和~~是很好的一個例子,使用這兩者可以將浮點轉成整型且效率方面要比同類的parseInt,Math.round 要快。在處理畫素及動畫位移等效果的時候會很有用。

 

function語句

 在Javascript中定義一個函式,有兩種寫法:

 

 function foo() { }//第一種

 var foo = function () { }//第二種

 

兩種寫法完全等價。但是在解析的時候,前一種寫法會被解析器自動提升到程式碼的頭部,因此違背了函式應該先定義後使用的要求,所以建議定義函式時,全部採用後一種寫法。

 

 

型別的包裝物件

JavaScript有一套型別的包裝物件。不要使用new Boolean、new Number或new String            也就是說不要像下面這樣

 

    new String("Hello World");
  new Number(2000);
  new Boolean(false); 

 

 

 

此外也請避免使用new Object和new Array,可使用{}和[]來代替

new

使用new時應謹慎,避免因為它而造成this的汙染全域性物件。

在JavaScript中類是這樣定義

 

  var Cat = function (name) {
    this.name = name;
    this.saying = 'meow' ;
  }

 

生成物件如下程式碼所示

  var myCat = new Cat('mimi');

這種利用函式生成類、利用new生成物件的語法,其實非常奇怪,一點都不符合直覺。而且,使用的時候,很容易忘記加上new,就會變成執行函式,然後莫名其妙多出幾個全域性變數。所以,建議不要這樣建立物件,而採用一種變通方法。

Douglas Crockford給出了一個函式:

  Object.beget = function (o) {
    var F = function (o) {};
    F.prototype = o ;
    return new F;
  };

建立物件時就利用這個函式,對原型物件進行操作:

  var Cat = {
    name:'',
    saying:'meow'
  };
  var myCat = Object.beget(Cat);

 

 

void

在JavaScript中,void是一個運算子,它接受一個運算數並返回undefined。這個命令沒什麼用,而且很令人困惑,建議避免使用。

 

相關文章