欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript 精粹讀書筆記(1,2)

 更新時間:2010年02月07日 11:29:09   作者:  
JavaScript的特性中有一部分特性帶來的麻煩遠遠超出它們的價值。
第1章 精華
JavaScript的特性中有一部分特性帶來的麻煩遠遠超出它們的價值。其中,一些特性是因為規(guī)范很不完善,從而可能導(dǎo)致可移植性的問題;一些特性會導(dǎo)致生成難以理解和修改的代碼;一些特性促使我的代碼風(fēng)格過于復(fù)雜且易于出錯;還有一些特性就是設(shè)計錯誤。有時候語言的設(shè)計者也會犯錯。
大多數(shù)編程語言都有精華部分和雞肋部分。我發(fā)現(xiàn)如果只使用精華部分而避免使用雞肋的部分,我可以成為一個更好的程序員。畢竟,用糟糕的部件怎么可能構(gòu)建出好東西呢?
標(biāo)準(zhǔn)委員會想要移除一門語言中的缺陷部分,這幾乎是不可能的,因為這樣做會損害所有依賴于那些雞肋部分的糟糕程序。除了在已存在的一大堆缺陷上堆積更多的特性,他們通常無能為力。并且新舊特性并不總是能和諧共處,可能從而產(chǎn)生出更多的雞肋部分。
但是,你有權(quán)力定義你自己的子集。你完全可以基于精華部分去編寫更好的程序。JavaScript中雞肋部分的比重超出了預(yù)料。在短到令人吃驚的時間里,它從不存在發(fā)展到全球采用。它從來沒有在實驗室里被試用和打磨。當(dāng)它還非常粗糙時,它就被直接集成到網(wǎng)景的Navigator 2瀏覽器中。隨著JavaTM的小應(yīng)用程序(Java applets)的失敗,JavaScript變成了默認(rèn)的“網(wǎng)頁語言”。作為一門編程語言,JavaScript的流行幾乎完全不受它的質(zhì)量的影響。
好在JavaScript有一些非常精華的部分。JavaScript最本質(zhì)的部分被深深地隱藏著,以至于多年來對它的主流觀點是:JavaScript就是一個丑陋的、沒用的玩具。本書的目的就是要揭示JavaScript中的精華,讓大家知道它是一門杰出的動態(tài)編程語言。
或許只學(xué)習(xí)精華部分的最大好處就是你可以不用考慮雞肋的部分。忘掉不好的模式是非常困難的。這是一個非常痛苦的工作,我們中的大多數(shù)人都會很不愿意面對。有時候,制定語言的子集是為了讓學(xué)生更好的學(xué)習(xí)。但在這里,我制定的JavaScript子集是為了主專業(yè)人員更好的工作。
1.1 為什么要使用JavaScript
JavaScript是一門重要的語言,因為它是web瀏覽器的語言。它與瀏覽器的結(jié)合使它成為世界上最流行的編程語言之一。同時,它也是世界上最被輕視的編程語言之一。瀏覽器的API和文檔對象模型(DOM)相當(dāng)糟糕,導(dǎo)致JavaScript遭到不公平的指責(zé)。
JavaScript是最被輕視的語言,因為它不是所謂的主流語言。如果你擅長某些主流語言,但卻在一個只支持JavaScript的環(huán)境中編程,那么被迫使用JavaScript確是相當(dāng)令人厭煩的。大多數(shù)人覺得沒必要去先學(xué)好JavaScript,但結(jié)果他們會驚訝地發(fā)現(xiàn),JavaScript跟他們寧愿使用的主流語言有很大不同,而且這些不同至為關(guān)鍵。
JavaScript令人驚異的事情是,在對這門語言沒有太多了解,甚至對編程都沒有太多了解的情況下,你也能用它來完成工作。它是一門擁有極強表達能力的語言。當(dāng)你知道要做什么時,它甚至能表現(xiàn)得更好。編程是很困難的事情。絕不應(yīng)該在對此一無所知時便開始你的工作。
1.2 分析JavaScript
JavaScript建立在一些非常好的想法和少數(shù)非常壞的想法之上。
那些非常好的想法包括函數(shù)、弱類型、動態(tài)對象和一個富有表現(xiàn)力的字面量表示法。那些壞的想法包括基于全局變量的編程模型。
JavaScript的函數(shù)是(主要)基于詞法作用域(lexical scoping)的頂級對象。JavaScript是第一個成為主流的lambda語言。實際上,相對Java而言,JavaScript與Lisp和Scheme有更多的共同點。它是披著C外衣的Lisp。這使得JavaScript成為一個非常強大的語言。
現(xiàn)今大部分編程語言中都流行要求強類型。其原理在于強類型允許編譯器在編譯時檢測錯誤。我們能越早檢測和修復(fù)錯誤,付出的代價就越小。JavaScript是一門弱類型的語言,所以JavaScript編譯器不能檢測出類型錯誤。另一方面,弱類型其實是自由的。我們無須建立復(fù)雜的次,我永遠不用做強制類型轉(zhuǎn)換,也不用疲于應(yīng)付類型系統(tǒng)以得到想要的行為。
JavaScript有非常強大的對象字面量表示法。通過列出對象的組成部分,它們就能簡單地被創(chuàng)建出來。這種表示法產(chǎn)生了流行的數(shù)據(jù)交換格式——JSON。
原型繼承是JavaScript中一個有爭議的特性。JavaScript有一個無類別(class-free)的對象系統(tǒng),在這個系統(tǒng)中,對象直接從其他對象繼承屬性。這真的很強大,但是對那些被訓(xùn)練使用類去創(chuàng)建對象的程序員們來說,原型繼承是一個陌生的概念。如果你嘗試對JavaScript直接應(yīng)用基于類的設(shè)計模式,你將會遭受挫折。但是,如果你學(xué)習(xí)使用JavaScript的原型本質(zhì),那么你的努力將會有所回報。
JavaScript在關(guān)鍵思想的選擇上飽受非議。雖然在大多數(shù)情況下,這些選擇是合適的。但是有一個選擇相當(dāng)糟糕:JavaScript依賴于全局變量來進行連接。所有編譯單元的所有頂級變量被撮合到一個被稱為全局對象的公共命名空間中。這是一件糟糕的事情,因為全局變量是魔鬼,并且在JavaScript中它們是基礎(chǔ)性的。
在少數(shù)情況下,我們不能忽略雞肋的部分。另外還有一些不可避免的糟粕,當(dāng)涉及這些部分時,我們會將它們指出來。如果你想學(xué)習(xí)那些雞肋的部分及如何拙劣地使用它們,請參閱任何其他的JavaScript書籍。
JavaScript是一門有許多差異的語言。它包含很多錯誤和尖銳的邊角(sharp edges),所以你可能會疑惑:“為什么我要使用JavaScript?”有兩個答案。第一個是你沒有選擇。Web已變成一個重要的應(yīng)用開發(fā)平臺,而JavaScript是唯一一門所有瀏覽器都可以識別的語言。很不幸,Java在瀏覽器環(huán)境中失敗了。JavaScript的蓬勃發(fā)展,恰恰說明了JavaScript確有其過人之處。
另一個答案是,盡管JavaScript有缺陷,但是它真的很優(yōu)秀。它既輕量又富有表現(xiàn)力。并且一旦你熟練掌握了它,就會發(fā)現(xiàn)函數(shù)式編程是一件很有趣的事。
但是為了更好地使用這門語言,你必須知道它的局限。我將會無情地揭示它們。不要因此而氣餒。這門語言的精華部分足以彌補它雞肋的不足。
1.3 一個簡單的試驗場
如果你有一個Web瀏覽器和任意一個文本編輯器,那么你就有了運行JavaScript程序所需要的一切。首先,請創(chuàng)建一個HTML文件,可以命名為program.html:
復(fù)制代碼 代碼如下:

<html>
<body>
<pre>
<script src="program.js"></script>
</pre>
</body>
</html>

接下來,在同一個文件夾內(nèi),創(chuàng)建一個腳本文件,可以命名為program.js:
document.writeln('Hello, world!');
下一步,用你的瀏覽器找開你的HTML文件去查看結(jié)果。本書貫徹始終都會用到一個method方法去定義新方法。下面是它的定義:
復(fù)制代碼 代碼如下:

Function.prototype.method=function(name,func){
this.prototype[name]=func;
return this;
}

我會在第4章解釋它。
第2章 語法
本章介紹JavaScript的精華部分的語法,并簡要地概述其語言結(jié)構(gòu)。
2.1 空白
空白可能表現(xiàn)為格式化字符或注釋的形式。空白通常沒有意義,但是偶爾須要用它來分隔字符序列,否則它們就會被合并成一個單一的符號。例如,對如下代碼來說:
var that = this;
var和that之間的空格是不能被移除的,但是其他的空格都可以被移除。
JavaScript提供兩種注釋形式,一種是用/* */包圍的塊注釋,另一種是以//為開頭的行注釋。注釋應(yīng)該被充分地用來提高程序的可讀性。必須注意的是,注釋一定要精確地描述代碼。沒有用的注釋比沒有注釋更糟糕。
用/* */包圍的塊注釋形式來自于一門叫PL/I(默然說話:Programming Language One的簡寫。當(dāng)中的“I”其實是羅馬數(shù)字的“一”,它是一種IBM公司在19世紀(jì)50年代發(fā)明的第三代高級編程語言)的語言。在JavaScript中,*/可能出現(xiàn)在正則表達式字面上,所以塊注釋對于被注釋的代碼塊來說是不安全的。例如:
/*
var rm_a = /a*/.match(s);
*/
導(dǎo)致了一個語法錯誤。所以,我建議避免使用/* */注釋,而用//注釋代替它。
2.2 標(biāo)識符
標(biāo)識符由一個字母開頭,其后可選擇性地加上一個或多個字母數(shù)字或下劃線。標(biāo)識符不能使用下面這些保留字:
abstract
boolean break byte
case catch char class const continue
debugger default delete do double
else enum export extends
false final finally float for function
goto
if implements import in instanceof int interface
long
native new null
package private protected public
return
short static super switch synchronized
this throw throws transient true try typeof
var volatile void
while with
在這個列表中的大部分保留字尚未用在這門語言中。這個列表不包括一些本應(yīng)該被保留而沒有保留的字,諸如undefined、NaN和Infinity。JavaScript不允許使用保留字來命名變量或參數(shù)。更糟糕的是,JavaScript不允許在對象字面量中,或者在一個屬性存取表達式的點號之后,使用保留字作為對象的屬性名。
標(biāo)識符被用于語句、變量、參數(shù)、屬性名、運算符和標(biāo)記。
2.3 數(shù)字
JavaScript只有一個單一的數(shù)字類型。它在內(nèi)部被表示為64位的浮點數(shù),和Java的double一樣。在JavaScript中,1和1.0是相同的值。
如果一個數(shù)字字面量有指數(shù)部分,那么這個字面量的值是由e之前的部分乘以10的e之后部分的次方計算出來的。所以100和1e2是相同的數(shù)字。
負(fù)數(shù)可以用前綴運算符-來構(gòu)成。
值NaN是一個數(shù)值,它表示一個不能產(chǎn)生正常結(jié)果的運算結(jié)果。NaN不等于任何值,包括它自己。你可以用函數(shù)isNaN(number)檢測NaN。
值Infinity表示所有大于1.79769313486231570e+308的值。
數(shù)字擁有方法(參見第8章)。JavaScript有一個對象Math,它包含一套作用于數(shù)字的方法。例如,可以用Math.floor(number)方法將一個數(shù)字轉(zhuǎn)換成一個整數(shù)。
2.4 字符串
字符串字面量可以被包圍在單引號或雙引號中,它可能包含0個或多個字符。\是轉(zhuǎn)義字符。JavaScript在被創(chuàng)建的時候,Unicode是一個16位的字符集,所以JavaScript中的所有字符都是16位的。
JavaScript沒有字符類型。要表示一個字符,只須創(chuàng)建僅包含一個字符的字符串即可。
轉(zhuǎn)義字符允許把那些正常情況下不被允許的字符插入到字符串中,比如反斜線、引號和控制字符。\u約定允許指定用數(shù)字表示的字符碼位。
“A”===”\u0041”
字符串有一個ength屬性。例如,”seven”.length是5。
字符串是不可變的。一旦字符串被創(chuàng)建,就永遠無法改變它。但通過+運算符去連接其他的字符串從而得到一個新字符串是很容易的。兩個包含著完全相同的字符且字符順序也相同的字符串被認(rèn)為是相同的字符串。所以:
‘c'+'a'+'t' === ‘cat'
是true。
字符串有一些方法(參見第8章)。
2.5 語句
一個編譯單元包含一組可執(zhí)行的語句。在web瀏覽器中,每個<script>標(biāo)簽都提供一個被編譯且立即執(zhí)行的編譯單元。因為缺少鏈接器,JavaScript把它們一起拋入一個公共的全局命名空間中。附錄A有更多關(guān)于全局變量的內(nèi)容。
當(dāng)var語句被用在函數(shù)的內(nèi)部時,它定義了這個函數(shù)的私有變量。
switch、while、for和do語句允許有一個可選的前置標(biāo)簽(label),它配合break語句來使用。
語句往往按照從上到下的順序被執(zhí)行。JavaScript可以通過條件語句(if和switch)、循環(huán)語句(while、for和do)、強制跳轉(zhuǎn)語句(break、return和throw)和函數(shù)調(diào)用來改變這個執(zhí)行序列。
代碼塊是包在一對花括號中的一組語句。不像許多其他的語言,JavaScript中的代碼塊不會創(chuàng)建一個新的作用域,因此變量應(yīng)該被定義在函數(shù)的頂端,而不是在代碼塊中。
if語句根據(jù)表達式的值改變程序的控制流程。如果表達式的值為真,那么執(zhí)行then代碼塊,否則,執(zhí)行可選的else分支。
下面列出的值被當(dāng)作假:
fase
null
undefined
數(shù)字0
數(shù)字NaN
其他所有的值都被當(dāng)作真,包括true,字符串”false”,以及所有的對象。
switch語句執(zhí)行一個多路分支。它把其表達式的值和所有指定的case條件進行匹配。其表達式可能產(chǎn)生一個數(shù)字或字符串。當(dāng)找到一個精確的匹配時,執(zhí)行匹配的case從句中的語句。如果沒有找到任何匹配,則執(zhí)行可選的default語句。
一個case從句包含一個或多個case表達式。case表達式不一定必須是常量。為了防止繼續(xù)執(zhí)行下一個case,case語句后應(yīng)該跟隨一上強制跳轉(zhuǎn)語句。你可以用break語句去退出一個switch語句。
while語句執(zhí)行一個簡單的循環(huán)。如果表達式值為假,那么循環(huán)將終止。而當(dāng)表達式值為真時,代碼塊將被執(zhí)行。
for語句是一個結(jié)構(gòu)更復(fù)雜的循環(huán)語句。它有兩種形式。
常見的形式由三個可選從句控制:初始化從句(initialization)、條件從句(condition)和增量從句(increment)。首先,;初始化從句被執(zhí)行,它的作用通常是初始化循環(huán)變量。接著計算條件從句的值。典型的情況是它根據(jù)一個完成條件檢測循環(huán)變量。如果條件從句被省略掉,則假定返回的條件是真。如果條件從句的值為假,那么循環(huán)將終止。否則,執(zhí)行代碼塊,然后執(zhí)行增量從句,接著循環(huán)會重復(fù)執(zhí)行條件從句。
另一種形式(被稱為for in語句)會枚舉一個對象的所有屬性名(或鍵名)。在每次循環(huán)中,對象的另一個屬性名字符串被賦值給for和in之間的變量。
通常你須通過檢測object.hasOwnProperty(variable)來確定這個屬性名就是該對象的成員,還是從其原型鏈里找到的。
復(fù)制代碼 代碼如下:

for(myvar in obj){
if(obj.hasOwnProperty(myvar)){

}
}

do語句就像while語句,唯一的區(qū)別是它在代碼塊執(zhí)行之后而不是之前檢測表達式的值。這就意味著代碼塊將總是要執(zhí)行至少一次。
try語句執(zhí)行一個代碼塊,并捕獲該代碼塊拋出的任何異常。catch從句定義了一個新的變量,它將接收該異常對象。
throw語句拋出一個異常。如果throw語句在一個try代碼塊中,那么控制權(quán)會跳到catch從句中。如果throw語句在函數(shù)中,則該函數(shù)調(diào)用被放棄,且控制權(quán)會跳到調(diào)用該函數(shù)的try語句的catch從句中。
throw語句中的表達式通常是一個對象字面量,它包含一個name屬性和一個message屬性。異常捕獲器可以使用這些信息去決定該做什么。
return語句會使一人函數(shù)提前返回。它也可以指定要被返回的值。如果沒有指定返回表達式,那么其返回值是undefined。
JavaScript不允許在return關(guān)鍵字和表達式之間換行。
break語句會使程序退出一個循環(huán)語句或switch語句。它可以指定一個可選的標(biāo)簽,那將會使程序退出帶該標(biāo)簽的語句。
JavaScript不允許在break關(guān)鍵字和標(biāo)簽之間換行。
一個expression語句可以給一個或多個變量或成員賦值,或者調(diào)用一個方法,或者從對象中刪除一個屬性。運算符=被用于賦值。不要把它和恒等運算符===混淆。運算符+=可以用于加法運算或連接字符串。
2.6 表達式
三元運算符?有三個運算數(shù)。如果第一個運算數(shù)值為真,它產(chǎn)生第二個運算數(shù)的值。但是,如果第一個運算數(shù)為假,它會產(chǎn)生第三個運算數(shù)的值。
表2-1:運算符優(yōu)先級
.[]()
屬性存取及函數(shù)調(diào)用
delete new typeof +-!
一元運算符
*/%
乘法、除法、取模
+-
加法/連接、減法
>= <= > <
不等式運算符
=== !==
等式運算符
&&
邏輯與
||
邏輯或
?:
三元
typeo運算符產(chǎn)生的值有'number'、'string'、'boolean'、'undefined'、'function'、'object'。如果運算數(shù)是一個數(shù)組或null,那么結(jié)果是'object',這是不對的。第6章和附錄A將會有更多關(guān)于typeof的內(nèi)容。
/運算符可能會產(chǎn)生一個非整數(shù)結(jié)果,即使兩個運算數(shù)都是整數(shù)。
函數(shù)調(diào)用引發(fā)函數(shù)的執(zhí)行。函數(shù)調(diào)用運算符是跟隨在函數(shù)名后面的一對圓括號。圓括號中可能包含將會傳遞給這個函數(shù)的參數(shù)。第4章將會有更多關(guān)于函數(shù)的內(nèi)容。
一個屬性存取表達式用于指定一個對象或數(shù)組的屬性或元素。下一章我將詳細描述它。
2.7 字面量
對象字面量是一種方便指定新對象的表示法。屬性名可以是標(biāo)識符或字符串。這些名字被當(dāng)作字面量名而不是變量名來對待,所以對象的屬性名在編譯時才能知道。屬性的值就是表達式。下一章將會有更多關(guān)于對象字面量的信息。
數(shù)組字面量是一個方便指定新數(shù)組的表示法。第6章將會有更多關(guān)于數(shù)組字面量的內(nèi)容。
第7章將會有更多關(guān)于正則表達式的內(nèi)容。
函數(shù)字面量定義了函數(shù)值。它可以有一個可選的名字,用于遞歸地調(diào)用自己。它可以指定一個參數(shù)列表,這些參數(shù)將作為變量由調(diào)用時傳遞的實際參數(shù)(arguments)初始化。函數(shù)的主體包括變量定義和語句。第4章將會有更多關(guān)于函數(shù)的內(nèi)容。

相關(guān)文章

最新評論