一: js 的10個(gè)設(shè)計(jì)缺陷
1)不適合開發(fā)大型程序
2)非常小的標(biāo)準(zhǔn)庫(kù)
Javascript提供的標(biāo)準(zhǔn)函數(shù)庫(kù)非常小秘车,只能完成一些基本操作蜕依,很多功能都不具備桅锄。
3)null和undefined
null屬于對(duì)象(object)的一種琉雳,意思是該對(duì)象為空;undefined則是一種數(shù)據(jù)類型竞滓,表示未定義咐吼。
4)全局變量難以控制
Javascript的全局變量,在所有模塊中都是可見的商佑;任何一個(gè)函數(shù)內(nèi)部都可以生成全局變量,這大大加劇了程序的復(fù)雜性厢塘。
5)自動(dòng)插入行尾分號(hào)
Javascript的所有語(yǔ)句茶没,都必須以分號(hào)結(jié)尾。但是晚碾,如果你忘記加分號(hào)抓半,解釋器并不報(bào)錯(cuò),而是為你自動(dòng)加上分號(hào)格嘁。有時(shí)候笛求,這會(huì)導(dǎo)致一些難以發(fā)現(xiàn)的錯(cuò)誤。
6)加號(hào)運(yùn)算符
+號(hào)作為運(yùn)算符糕簿,有兩個(gè)含義探入,可以表示數(shù)字與數(shù)字的和,也可以表示字符與字符的連接懂诗。如果一個(gè)操作項(xiàng)是字符蜂嗽,另一個(gè)操作項(xiàng)是數(shù)字,則數(shù)字自動(dòng)轉(zhuǎn)化為字符
7)NaN
NaN是一種數(shù)字殃恒,表示超出了解釋器的極限植旧。它有一些很奇怪的特性:與其設(shè)計(jì)NaN,不如解釋器直接報(bào)錯(cuò)离唐,反而有利于簡(jiǎn)化程序病附。
8)數(shù)組和對(duì)象的區(qū)分
由于Javascript的數(shù)組也屬于對(duì)象(object),所以要區(qū)分一個(gè)對(duì)象到底是不是數(shù)組亥鬓,相當(dāng)麻煩
9)== 和 ===
==用來(lái)判斷兩個(gè)值是否相等完沪。當(dāng)兩個(gè)值類型不同時(shí),會(huì)發(fā)生自動(dòng)轉(zhuǎn)換贮竟,得到的結(jié)果非常不符合直覺丽焊。因此,推薦任何時(shí)候都使用"==="(精確判斷)比較符咕别。
10)基本類型的包裝對(duì)象
Javascript有三種基本數(shù)據(jù)類型:字符串技健、數(shù)字和布爾值。它們都有相應(yīng)的建構(gòu)函數(shù)惰拱,可以生成字符串對(duì)象雌贱、數(shù)字對(duì)象和布爾值對(duì)象啊送。與基本數(shù)據(jù)類型對(duì)應(yīng)的對(duì)象類型,作用很小欣孤,造成的混淆卻很大
二: 12中不宜使用的JS語(yǔ)法
1. ==
Javascript有兩組相等運(yùn)算符馋没,一組是==和!=,另一組是===和!==降传。前者只比較值的相等篷朵,后者除了值以外,還比較類型是否相同婆排。
請(qǐng)盡量不要使用前一組声旺,永遠(yuǎn)只使用===和!==。因?yàn)?=默認(rèn)會(huì)進(jìn)行類型轉(zhuǎn)換段只,規(guī)則十分難記腮猖。如果你不相信的話,請(qǐng)回答下面五個(gè)判斷式的值是true還是false:
false == 'false'
false == undefined
false == null
null == undefined
0 == ''
前三個(gè)是false赞枕,后兩個(gè)是true澈缺。
2. with
with的本意是減少鍵盤輸入。比如
obj.a = obj.b;
obj.c = obj.d;
可以簡(jiǎn)寫成
with(obj) { ?a = b; ? c = d; ? }
但是炕婶,在實(shí)際運(yùn)行時(shí)姐赡,解釋器會(huì)首先判斷obj.b和obj.d是否存在,如果不存在的話古话,再判斷全局變量b和d是否存在雏吭。這樣就導(dǎo)致了低效率,而且可能會(huì)導(dǎo)致意外陪踩,因此最好不要使用with語(yǔ)句杖们。
3. eval
eval用來(lái)直接執(zhí)行一個(gè)字符串。這條語(yǔ)句也是不應(yīng)該使用的肩狂,因?yàn)樗行阅芎桶踩缘膯栴}摘完,并且使得代碼更難閱讀。
eval能夠做到的事情傻谁,不用它也能做到孝治。比如
eval("myValue = myObject." + myKey + ";");
可以直接寫成
myValue = myObject[myKey];
至于ajax操作返回的json字符串,可以使用官方網(wǎng)站提供的解析器json_parse.js運(yùn)行审磁。
4. continue
這條命令的作用是返回到循環(huán)的頭部谈飒,但是循環(huán)本來(lái)就會(huì)返回到頭部。所以通過適當(dāng)?shù)臉?gòu)造态蒂,完全可以避免使用這條命令杭措,使得效率得到改善。
5. switch 貫穿
switch結(jié)構(gòu)中的case語(yǔ)句钾恢,默認(rèn)是順序執(zhí)行手素,除非遇到break鸳址,return和throw。有的程序員喜歡利用這個(gè)特點(diǎn)泉懦,比如
switch(n) { ? case 1: ? ? case 2: ? ?break; ?}
這樣寫容易出錯(cuò)稿黍,而且難以發(fā)現(xiàn)。因此建議避免switch貫穿崩哩,凡是有case的地方巡球,一律加上break。
switch(n) { ? ?case 1: ? break;
case 2: ? ?break; ? }
6. 單行的塊結(jié)構(gòu)
if邓嘹、while辕漂、do和for,都是塊結(jié)構(gòu)語(yǔ)句吴超,但是也可以接受單行命令。比如
if (ok) t = true;
甚至寫成
if (ok) ? t = true;
這樣不利于閱讀代碼鸯乃,而且將來(lái)添加語(yǔ)句時(shí)非常容易出錯(cuò)鲸阻。建議不管是否只有一行命令,都一律加上大括號(hào)缨睡。
if (ok){ ?t = true; ?}
7. ++和--
遞增運(yùn)算符++和遞減運(yùn)算符--鸟悴,直接來(lái)自C語(yǔ)言倦踢,表面上可以讓代碼變得很緊湊复凳,但是實(shí)際上會(huì)讓代碼看上去更復(fù)雜和更晦澀炬太。因此為了代碼的整潔性和易讀性逞盆,不用為好蚯撩。
8. 位運(yùn)算符
Javascript完全套用了Java的位運(yùn)算符殴玛,包括按位與&擎宝、按位或|郁惜、按位異或^水评、按位非~猩系、左移<<、帶符號(hào)的右移>>和用0補(bǔ)足的右移>>>中燥。
這套運(yùn)算符針對(duì)的是整數(shù)寇甸,所以對(duì)Javascript完全無(wú)用,因?yàn)镴avascript內(nèi)部疗涉,所有數(shù)字都保存為雙精度浮點(diǎn)數(shù)拿霉。如果使用它們的話,Javascript不得不將運(yùn)算數(shù)先轉(zhuǎn)為整數(shù)咱扣,然后再進(jìn)行運(yùn)算绽淘,這樣就降低了速度。而且"按位與運(yùn)算符"&同"邏輯與運(yùn)算符"&&偏窝,很容易混淆收恢。
9. function語(yǔ)句
在Javascript中定義一個(gè)函數(shù)武学,有兩種寫法:
function foo() { }
和
var foo = function () { }
兩種寫法完全等價(jià)。但是在解析的時(shí)候伦意,前一種寫法會(huì)被解析器自動(dòng)提升到代碼的頭部火窒,因此違背了函數(shù)應(yīng)該先定義后使用的要求,所以建議定義函數(shù)時(shí)驮肉,全部采用后一種寫法熏矿。
10. 基本數(shù)據(jù)類型的包裝對(duì)象
Javascript的基本數(shù)據(jù)類型包括字符串、數(shù)字离钝、布爾值票编,它們都有對(duì)應(yīng)的包裝對(duì)象String、Number和Boolean卵渴。所以慧域,有人會(huì)這樣定義相關(guān)值:
new String("Hello World");
new Number(2000);
new Boolean(false);
這樣寫完全沒有必要,而且非常費(fèi)解浪读,因此建議不要使用昔榴。
另外,new Object和new Array也不建議使用碘橘,可以用{}和[]代替互订。
11. new語(yǔ)句
Javascript是世界上第一個(gè)被大量使用的支持Lambda函數(shù)的語(yǔ)言,本質(zhì)上屬于與Lisp同類的函數(shù)式編程語(yǔ)言痘拆。但是當(dāng)前世界仰禽,90%以上的程序員都是使用面向?qū)ο缶幊獭榱丝拷髁鞣那琂avascript做出了妥協(xié)吐葵,采納了類的概念,允許根據(jù)類生成對(duì)象犹撒。
類是這樣定義的:
var Cat = function (name) {
this.name = name;
this.saying = 'meow' ;
}
然后折联,再生成一個(gè)對(duì)象
var myCat = new Cat('mimi');
這種利用函數(shù)生成類、利用new生成對(duì)象的語(yǔ)法识颊,其實(shí)非常奇怪诚镰,一點(diǎn)都不符合直覺。而且祥款,使用的時(shí)候清笨,很容易忘記加上new,就會(huì)變成執(zhí)行函數(shù)刃跛,然后莫名其妙多出幾個(gè)全局變量抠艾。所以,建議不要這樣創(chuàng)建對(duì)象桨昙,而采用一種變通方法检号。
Douglas Crockford給出了一個(gè)函數(shù):
Object.beget = function (o) {
var F = function (o) {};
F.prototype = o ;
return new F;
};
創(chuàng)建對(duì)象時(shí)就利用這個(gè)函數(shù)腌歉,對(duì)原型對(duì)象進(jìn)行操作:
var Cat = {
name:'',
saying:'meow'
};
var myCat = Object.beget(Cat);
對(duì)象生成后,可以自行對(duì)相關(guān)屬性進(jìn)行賦值:
myCat.name = 'mimi';
12. void
在大多數(shù)語(yǔ)言中齐苛,void都是一種類型翘盖,表示沒有值。但是在Javascript中凹蜂,void是一個(gè)運(yùn)算符馍驯,接受一個(gè)運(yùn)算數(shù),并返回undefined玛痊。
void 0; // undefined
這個(gè)命令沒什么用汰瘫,而且很令人困惑,建議避免使用擂煞。