JS紅色警戒
JS有很多讓人迷惑的地方点晴,一起來看看吧。
with
with可以擴展作用域鏈瓮下,建議永遠不要使用它盖腕。我們來看看這些列子。
案例1
正常用法
function People(name){
this.name = name;
this.eat = function(){
console.log(this.name+"要吃飯");
}
}
var me = new People("xiaohu");
with(me){
console.log(name);//可以省略me.
eat();//可以省略me.
}
看起來很方便的樣子并巍。
with讓閱讀代碼的人很瘋狂
看看下面的代碼
with(me){
console.log(name);
eat();
play=function(){//如果是省略了me.,那么play應(yīng)該定義在對象me中
console.log(this.name);
}
nickName="xiao" + name;//如果是省略了me.,那么nickName應(yīng)該定義在對象me中
}
我們運行一下就知道目木,兩個變量變成了全局變量。
案例2
正常用法
function People(name){
this.name = name;
this.property={
wallet:{
banknote:1000,
coin:20,
salary:9
}
};
this.eat = function(){
console.log(this.name+"要吃飯");
}
}
var me = new People("xiaohu");
var salary=2000;
with(me.property.wallet){//好像很方便啊
banknote+=salary;//等等懊渡,salary到底是me.property.wallet還是哪兒的肮羯洹?
console.log(banknote);
}
with讓閱讀代碼的人很瘋狂
我們還是用其他方法吧剃执。
var salary=2000;
var wallet = me.property.wallet;
wallet.banknote+=salary;
console.log(wallet.banknote);
像這樣緩存起來就很好var wallet = me.property.wallet;
eval
eval容易出錯
JS的eval可能會使代碼不清晰誓禁,影響調(diào)試和性能,應(yīng)該避免使用肾档∧∏。看看下面這段代碼。
function Workers(){
this.assignment=function assignment(who, number){
eval("this.work" + who + "='finish task:"+number+"'");
}
}
var workers = new Workers();
for (var i = 0; i < 5; i++) {
workers.assignment(i,i);
}
這段代碼給工人分配工作怒见,在對象workers創(chuàng)建很多的屬性俗慈,eval實際上想執(zhí)行這樣的語句workers.work1='finin task:1'
。在參數(shù)一切正常的情況下是可以很好的工作的速种,但是這個函數(shù)是很容易出錯的姜盈。
像下面這樣傳入空格,“'”等字符串的結(jié)束標記配阵,都會讓eval嘗試運行的語句是不合法的,非常容易出錯示血,也不容易調(diào)試棋傍。
workers.assignment("1 1","'");
eval最常見的錯誤就是像上面這樣給對象加很多屬性,其實用數(shù)組就可以很好的實現(xiàn)同樣的功能∧焉螅看看下面的代碼瘫拣。
function WorkersBetter(){
this.workers=[];
this.assignment=function assignment(name, task){
//TODO: 檢查數(shù)組越界......
var obj ={name:name,task:task};
this.workers.push(obj);
}
}
var workersBetter = new WorkersBetter();
for (var i = 0; i < 3; i++) {
workersBetter.assignment(i,"task"+i);
}
用eval容易被注入代碼
看看這段代碼,你只想賦值告喊,彈出了對話框
workers.assignment("1","';alert('xiaohu');'");
在看看用eval解析json字符串的用法麸拄。同樣這樣也會讓人注入代碼,而且性能不好黔姜。
var jsonString='{"task":"write better javascript!"}';
var json = eval('('+jsonString+')');
console.log(json);
正確的做法應(yīng)該用專門解析json的函數(shù)或者第三方庫
console.log(JSON.parse(jsonString));
括號
條件判斷應(yīng)該加括號拢切,并且成對出現(xiàn),但是就是有人喜歡節(jié)省點秆吵,這樣真實坑死隊友啊淮椰。看看下面這樣的代碼
var isGoodCoder=false;
var salary=0,vacation=0;
if(isGoodCoder)
salary=10000;
vacation=30;
上面的vacation=30;
已經(jīng)不在if的控制范圍里面了,好一些的寫法應(yīng)該這樣
if(isGoodCoder){
salary=10000;
vacation=30;
}else{
salary=1000;
vacation=5;
}
數(shù)字問題
精度問題
程序并不能精確的保存和運算浮點數(shù)(小數(shù))主穗。我們看看JS如何處理這種情況泻拦。
0.1 + 0.2
=>0.30000000000000004
可以看到多出了0.00000000000000004
,如果我們要用==
或者和別的數(shù)字做運輸忽媒,就會有問題争拐。使用toFixed
保存精度。
(0.1 + 0.2).toFixed(1);
=>"0.3"
雖然toFixed
處理了精度問題晦雨,但是卻返回了字符串陆错,還要用parseFloat
處理一下
parseFloat((0.1 + 0.2).toFixed(1));
parseFloat,parseInt可以從字符串中解析出數(shù)字。不過只能解析出以數(shù)字開頭的字符串金赦。
看一下下面的代碼音瓷。
parseFloat("2.333是xiaohu的零用錢");//=>2.333
parseFloat("xiaohu的零用錢為2.333");//=>NaN
進制轉(zhuǎn)換
parseInt(string, radix);
radix
一個2到36之間的整數(shù)值,用于指定轉(zhuǎn)換中采用的基數(shù)夹抗。比如參數(shù)"10"表示使用我們通常使用的十進制數(shù)值系統(tǒng)绳慎。總是指定該參數(shù)可以消除閱讀該代碼時的困惑并且保證轉(zhuǎn)換結(jié)果可預(yù)測漠烧。當忽略該參數(shù)時杏愤,不同的實現(xiàn)環(huán)境可能產(chǎn)生不同的結(jié)果。
看看如下代碼:
parseInt(021);//=>17已脓,八進制2*8^1+1*8^0=17
parseInt(021,10);//=>17珊楼,貌似第一個參數(shù)指定了進制,第二個參數(shù)沒啥用處度液?
parseInt("021");//老得js標志和新的標準不一樣厕宗,新的標準會返回21
parseInt("021",10);//=>21,這種方式才是最安全堕担。
parseInt("021",10);
是最好的已慢。
判斷是否是數(shù)字
typeof data === "number"
可以判斷一個變量是否是number類型。好像情況已經(jīng)很簡單了霹购。但是JS有一個NaN佑惠,表示不是一個數(shù)字。但是typeof NaN === "number"
卻返回true齐疙。所以我們最好使用下面這個代碼判斷是否是數(shù)字膜楷,來處理這個特殊情況。
function isNumber(data){
return ( typeof data === "number"
&& !isNaN(data) );
}
強制轉(zhuǎn)換
var hasAge = !!age;
這為啥要寫2個‘贞奋!’ 赌厅?
實際上!!age === Boolean(age)
,所以!!
相當于強制轉(zhuǎn)換成Boolean
類型了忆矛。
另外這樣也可以強制轉(zhuǎn)換
var a = '12';
//+a就是數(shù)字12.
想了解強制轉(zhuǎn)換的更多細節(jié)可以查看Javascript 強制類型轉(zhuǎn)換函數(shù)