1.了解你使用的javascript版本。
- "use strict"只有在腳本或函數(shù)的頂部才能生效缤削。
- 應對代碼連接,編寫健壯代碼的兩個方案:
- 不要將進行嚴格模式檢查和不進行嚴格模式檢查的文件連接起來
- 連接多個文件時寞酿,將自身包裹在立即調(diào)用的函數(shù)表達式中
// 最外層不進行嚴格模式檢查
(function(){
// file1.js
"use strict"
function(){
// ...
}
// ...
})()
(function(){
// file2.js沒有進行嚴格模式檢查
function(){
var arguments = [];
// ...
}
})()
- 要獲得最大兼容性祟敛,最簡單的方法是在嚴格模式下編寫代碼,并顯式的將代碼包裹在本地啟用了嚴格模式的函數(shù)中佣蓉。
(function(){
'use strict';
function f(){
//...
}
//...
})()
2.理解Javascript浮點數(shù)
- JavaScript中所有的數(shù)字都是雙精度浮點數(shù)
- 位運算符將數(shù)字視為32位的有符號整數(shù)
- 浮點運算只能四舍五入到最接近的可表示的實數(shù)披摄,盡可能采用整數(shù)值運算
(0.1 + 0.2) + 0.3; // 0.6000000000000001
0.1 + (0.2 + 0.3); // 0.6
3.當心隱式的強制轉(zhuǎn)換
- JavaScript將值強制轉(zhuǎn)換為期望的類型。
3 + true; // 4
"2" + 3; // "23"
(1 + 2) + "3"; // "33"
"17" * 3; // 51
"8" | "1"; // 9
- 一個未定義的變量將被轉(zhuǎn)換為特殊的浮點數(shù)值NaN勇凭,NaN是唯一一個不等于其自身的值疚膊。
isNaN(Nan); //true
isNaN("foo"); // true
isNaN(undefined); // true
isNaN({}); // true
isNaN({valueof: "foo"}); // true
function isReallyNaN(x){
return x !== x;
}
- 對象可以被強制轉(zhuǎn)換為原始值。最常見的用法是轉(zhuǎn)換為字符串(通過隱式調(diào)用自身的toString方法)虾标。
"the Math object: " + Math; // "the Math object: [object Math]"
- 對象通過valueOf方法強制轉(zhuǎn)換為數(shù)字寓盗,通過toString()方法強制轉(zhuǎn)換為字符串。
- 具有valueOf方法的對象應該實現(xiàn)一個toString方法璧函,返回一個valueOf方法產(chǎn)生的數(shù)字的字符串表示傀蚌。
- 測試一個值是否為未定義的值,應該使用typeOf或者與undefined比較而不是使用真值運算蘸吓。JavaScript中有7個假值: false喳张、0、-0美澳、""、NaN摸航、null制跟、undefined。
function point(x, y){
if( !x ){
x = 320;
}
if( !y ){
y = 240;
}
return { x: x, y: y }
}
point(0,0); // 忽略任何假值參數(shù)酱虎,包括0雨膨,結(jié)果為{ x: 320, y: 240 }
對比下面的typeof檢查方式
function point(x, y){
if(typeof x === "undefined"){
x = 320;
}
if(typeof y === "undefined"){
y = 240;
}
return { x: x, y: y }
}
point(); // { x: 320, y: 240 }
point(0,0); // { x: 0, y: 0 }
4.原始類型優(yōu)于封裝
JavaScript除了布爾、數(shù)字读串、字符串聊记、null、undefined是原始值
類型外恢暖,其余的全是對象
排监。但是typeof(null)得到的結(jié)果卻是'object'
,ECMAScript標準描述這是一個獨特類型杰捂。標準庫提供了構(gòu)造函數(shù)來封裝布爾值舆床、數(shù)字、字符串作為對象。
var s = "hello"
var so = new String("hello");//封裝字符串的String對象
typeof s // "string"
typeof so; // object
不能使用內(nèi)置操作符比較兩個String對象挨队,因為每個String對象都只等于自身:
"hello"==="hello"; //true
var s1 = new String("hello")
var s2 = new String("hello")
s1===s2; // false
s1==s2; //false
對原始值提取屬性和進行方法調(diào)用時谷暮,它表現(xiàn)的像使用了對應對象類型封裝了該值
一樣。例如盛垦,String對象的方法湿弦,對原始字符串也可以調(diào)用那個。
"hello".toUpperCase(); // "HELLO"
// 對比下面的調(diào)用
"hello".someProperty =17; // 封裝成對象A
"hello".someProperty; // 封裝成對象B腾夯,undefined
5.避免對混合類型使用==運算符
下面是一個隱式強制轉(zhuǎn)換的例子颊埃,運算符兩邊都被強制轉(zhuǎn)換為數(shù)字1。
"1.0e0" == { valueOf: function(){ return true; } }; // true
當兩個參數(shù)屬于同一類型時俯在,==和===運算符可以互換竟秫,但最好嚴格使用相等運算符。對比下面三個版本的代碼:
bad
var today = new Date();
if(form.month.value == (today.getMonth() + 1) && form.day.value == today.getDate()){}
better: 顯示使用Number函數(shù)或一元運算符+將值轉(zhuǎn)換為數(shù)字
var today = new Date();
if(+form.month.value == (today.getMonth() + 1) && +form.day.value == today.getDate()){}
best: 使用嚴格相等運算符
var today = new Date();
if(form.month.value === (today.getMonth() + 1) && form.day.value === today.getDate()){}
6.了解分號插入的局限
- 分號僅在
}標記之前
跷乐、一個或多個換行之后
和程序輸入的結(jié)尾
被插入肥败。 - 分號僅在
隨后的輸入標記不能解析
時插入。
你可能會想愕提,只要不省略分號就沒事了馒稍。事實上不是這樣。接下來是個JavaScript語法限制產(chǎn)生式(restricted production)浅侨,它不允許兩個字符之間出現(xiàn)換行纽谒。最危險的是return語句,在return關鍵字和其可選參數(shù)之間不能包含換行符如输。
return {}; // 返回新對象
//
return
{}; // 出現(xiàn)換行符被解析為3條語句 return, {}, ;