<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] ## 基本句法和變量 ### 語句 JavaScript程序的執行單位為行(line),也就是一行一行地執行。一般情況下,每一行就是一個語句。 語句(statement)是為了完成某種任務而進行的操作,比如下面就是一行賦值語句: ~~~ var a = 1 + 3; ~~~ 這條語句先用var命令,聲明了變量a,然后將`1 + 3`的運算結果賦值給變量a。 `1 + 3`叫做表達式(expression),指一個為了得到返回值的計算式。語句和表達式的區別在于,前者主要為了進行某種操作,一般情況下不需要返回值;后者則是為了得到返回值,一定會返回一個值。 凡是JavaScript語言中預期為值的地方,都可以使用表達式。比如,賦值語句的等號右邊,預期是一個值,因此可以放置各種表達式。一條語句可以包含多個表達式。 語句以分號結尾,一個分號就表示一個語句結束。多個語句可以寫在一行內。 ~~~ var a = 1 + 3 ; var b = "abc"; ~~~ 分號前面可以沒有任何內容,JavaScript引擎將其視為空語句。 ~~~ ;;; ~~~ 上面的代碼就表示3個空語句。(關于分號的更多介紹,請看后文《結尾的分號》一節。) 表達式不需要分號結尾。一旦在表達式后面添加分號,則JavaScript引擎就將表達式視為語句,這樣會產生一些沒有任何意義的語句。 ~~~ 1 + 3; "abc"; ~~~ 上面兩行語句有返回值,但是沒有任何意義,因為只是返回一個單純的值,沒有任何其他操作。 ### 變量 變量是對“值”的引用,使用變量等同于引用一個值。每一個變量都有一個變量名。 ~~~ var a = 1; ~~~ 上面的代碼先聲明變量a,然后在變量a與數值1之間建立引用關系,也稱將數值1“賦值”給變量a。以后,引用變量a就會得到數值1。最前面的var,是變量聲明命令。它表示通知解釋引擎,要創建一個變量a。 變量的聲明和賦值,是分開的兩個步驟,上面的代碼將它們合在了一起,實際的步驟是下面這樣。 ~~~ var a; a = 1; ~~~ 如果只是聲明變量而沒有賦值,則該變量的值為undefined。 ~~~ var a; a // undefined ~~~ JavaScript允許省略var,直接對未聲明的變量賦值。也就是說,var a = 1 與 a = 1,這兩條語句的效果相同。但是由于這樣的做法很容易不知不覺地創建全局變量(尤其是在函數內部),所以建議總是使用var命令聲明變量。 > 嚴格地說,var a = 1 與 a = 1,這兩條語句的效果不完全一樣,主要體現在delete命令無法刪除前者。不過,絕大多數情況下,這種差異是可以忽略的。 如果一個變量沒有聲明就直接使用,JavaScript會報錯,告訴你變量未定義。 ~~~ x // ReferenceError: x is not defined ~~~ 上面代碼直接使用變量x,系統就報錯,告訴你變量x沒有聲明。 可以在同一條var命令中聲明多個變量。 ~~~ var a,b; ~~~ JavaScirpt是一種動態類型語言,也就是說,變量的類型沒有限制,可以賦予各種類型的值。 ~~~ var a = 1; a = "hello"; ~~~ 上面代碼中,變量a起先被賦值為一個數值,后來又被重新賦值為一個字符串。第二次賦值的時候,因為變量a已經存在,所以不需要使用var命令。如果用了,就等于重新聲明一個變量a,會覆蓋掉前面的同名變量。 ### 變量提升 JavaScript引擎的工作方式是,先解析代碼,獲取所有被聲明的變量,然后再一行一行地運行。這造成的結果,就是所有的變量的聲明語句,都會被提升到代碼的頭部,這就叫做變量提升(hoisting)。 ~~~ console.log(a); var a = 1; ~~~ 上面代碼首先使用console.log方法,在控制臺(console)顯示變量a的值。這時變量a還沒有聲明和賦值,所以這是一種錯誤的做法,但是實際上不會報錯。因為存在變量提升,真正運行的是下面的代碼: ~~~ var a; console.log(a); a = 1; ~~~ 最后的結果是顯示undefined,表示變量a已聲明,但還未賦值。 請注意,變量提升只對var命令聲明的變量有效,如果一個變量不是用var命令聲明的,就不會發生變量提升。 ~~~ console.log(b); b = 1; ~~~ 上面的語句將會報錯,提示“ReferenceError: b is not defined”,即變量b未聲明,這是因為b不是用var命令聲明的,JavaScript引擎不會將其提升,而只是視為對頂層對象的b屬性的賦值。 ### 標識符 標識符(identifier)是用來識別具體對象的一個名稱。最常見的標識符就是變量名,以及后面要提到的函數名。JavaScript語言的標識符對大小寫敏感,所以a和A是兩個不同的標識符。 標識符有一套命名規則,不符合規則的就是非法標識符。JavaScript引擎遇到非法標識符,就會報錯。 簡單說,標識符命名規則如下: * 第一個字符可以是任意Unicode字母,以及美元符號($)和下劃線(_)。 * 第二個字符及后面的字符,還可以用數字。 下面這些都是合法的標識符。 ~~~ arg0 _tmp $elem π ~~~ 下面這些則是不合法的標識符。 ~~~ 1a 23 *** a+b -d ~~~ 中文是合法的標識符,可以用作變量名。 ~~~ var 臨時變量 = 1; ~~~ > JavaScript有一些保留字,不能用作標識符:arguments、break、case、catch、class、const、continue、debugger、default、delete、do、else、enum、eval、export、extends、false、finally、for、function、if、implements、import、in、instanceof、interface、let、new、null、package、private、protected、public、return、static、super、switch、this、throw、true、try、typeof、var、void、while、with、yield。 另外,還有三個詞雖然不是保留字,但是因為具有特別含義,也不應該用作標識符:Infinity、NaN、undefined。 ### 注釋 源碼中被JavaScript引擎忽略的部分就叫做注釋,它的作用是對代碼進行解釋。Javascript提供兩種注釋:一種是單行注釋,用//起頭;另一種是多行注釋,放在/* 和 */之間。 ~~~ // 這是單行注釋 /* 這是 多行 注釋 */ ~~~ 本教程后面的代碼部分,會采用這兩種形式說明代碼的運行結果,以及需要注意的地方。 此外,由于歷史上JavaScript兼容HTML代碼的注釋,所以也被視為單行注釋。 ~~~ x = 1; <!-- x = 2; --> x = 3; ~~~ 上面代碼中,只有`x = 1`會執行,其他的部分都被注釋掉了。 需要注意的是,-->只有在行首,才會被當成單行注釋,否則就是一個運算符。 ~~~ function countdown(n) { while (n --> 0) console.log(n); } countdown(3) // 2 // 1 // 0 ~~~ 上面代碼中,`n --> 0`實際上會當作`n-- > 0`,因為輸出2、1、0。 ### 區塊 JavaScript使用大括號,將多個相關的語句組合在一起,稱為“區塊”(block)。 與大多數編程語言不一樣,JavaScript的區塊不構成單獨的作用域(scope)。也就是說,區塊中的變量與區塊外的變量,屬于同一個作用域。 ~~~ { var a = 1; } a // 1 ~~~ 上面代碼在區塊內部,聲明并賦值了變量a,然后在區塊外部,變量a依然有效,這說明區塊不構成單獨的作用域,與不使用區塊的情況沒有任何區別。所以,單獨使用的區塊在JavaScript中意義不大,很少出現。區塊往往用來構成其他更復雜的語法結構,比如for、if、while、functions等。 ### 條件語句 JavaScript提供if結構和switch結構,完成條件判斷。 (1)if 結構 if結構先判斷一個表達式的布爾值,然后根據布爾值的真偽,執行不同的語句。 ~~~ if (expression) statement ~~~ 上面是if結構的基本形式。需要注意的是,expression(表達式)必須放在圓括號中,表示對表達式求值。如果結果為true,就執行緊跟在后面的statement(語句);如果結果為false,則跳過statement。 ~~~ if (m === 3) m += 1; ~~~ 上面代碼表示,只有在m等于3時,才會將其值加上1。 這種寫法要求statement只能有一個語句。如果想將多個語句放在statement之中,必須在if的條件判斷之后,加上大括號。 ~~~ if (m === 3) { m += 1; } ~~~ 建議總是在if語句中使用大括號,因為這樣方便插入語句。 (2)if...else結構 if代碼塊后面,還可以跟一個else代碼塊,表示括號中的表示式為false時,所要執行的代碼。 ~~~ if (m === 3) { // then } else { // else } ~~~ 上面代碼判斷變量m是否等于3,如果等于就執行if代碼塊,否則執行else代碼塊。 對同一個變量進行多次判斷時,多個if...else語句可以連寫在一起。 ~~~ if (m === 0) { // ... } else if (m === 1) { // ... } else if (m === 2) { // ... } else { // ... } ~~~ else代碼塊總是跟隨離自己最近的那個if語句。 ~~~ var m = 1; var n = 2; if (m !== 1) if (n === 2) console.log('hello'); else console.log('world'); ~~~ 上面代碼不會有任何輸出,else代碼塊也不會得到執行,因為它跟著的是最近的那個if語句,相當于下面這樣。 ~~~ if (m !== 1) { if (n === 2) { console.log('hello'); } else { console.log('world'); } } ~~~ 如果想讓else代碼塊跟隨最上面的那個if語句,就要改變大括號的位置。 ~~~ if (m !== 1) { if (n === 2) { console.log('hello'); } } else { console.log('world'); } // world ~~~ (3)switch結構 多個if...else連在一起使用的時候,可以轉為使用更方便的switch結構。 ~~~ switch (fruit) { case "banana": // ... break; case "apple": // ... break; default: // ... } ~~~ 上面代碼根據變量fruit的值,選擇執行相應的case。如果所有case都不符合,則執行最后的default部分。需要注意的是,每個case代碼塊內部的break語句不能少,否則會接下去執行下一個case代碼塊,而不是跳出switch結構。 switch語句部分和case語句部分,都可以使用表達式。 ~~~ switch(1 + 3) { case 2 + 2: f(); break; default: neverhappens(); } ~~~ 上面代碼的default部分,是永遠不會執行到的。 需要注意的是,switch語句后面的表達式與case語句后面的表示式,在比較運行結果時,采用的是嚴格相等運算符(===),而不是相等運算符(==),這意味著比較時不會發生類型轉換。 switch結構不利于代碼重用,往往可以用對象形式重寫。 ~~~ var o = { banana: function (){ return }, apple: function (){ return }, default: function (){ return } }; if (o[fruit]){ o[fruit](); } else { o['default'](); } ~~~ ### 循環語句 循環語句用于重復執行某個操作,它有多種形式。 (1)while循環 While語句包括一個循環條件,只要該條件為真,就不斷循環。 ~~~ while (expression) statement ~~~ while語句的循環條件是一個表達式(express),必須放在圓括號中。語句(statement)部分默認只能寫一條語句,如果需要包括多條語句,必須添加大括號。 ~~~ while (expression){ statement } ~~~ 下面是while語句的一個例子。 ~~~ var i = 0; while (i<100){ console.log('i當前為:' + i); i++; } ~~~ 上面的代碼將循環100次,直到i等于100為止。 (2)for循環 for語句是循環命令的另一種形式。 ~~~ for(initialize; test; increment) statement // 或者 for(initialize; test; increment){ statement } ~~~ 它分成三步: * 初始化(initialize):確定循環的初始值,只在循環開始時執行一次; * 測試(test):檢查循環條件,只要為真就進行后續操作; * 遞增(increment):完成后續操作,然后返回上一步,再一次檢查循環條件。 下面是一個循環打印數組每個元素的例子。 ~~~ for (var i=0; i < arr.length; i++) { console.log(arr[i]); } ~~~ 所有for循環,都可以改寫成while循環。 ~~~ var i = 0; while (i < arr.length) { console.log(arr[i]); i++; } ~~~ for語句表達式的三個部分(initialize,test,increment),可以省略任何一個,也可以全部省略。 ~~~ for (;;){ console.log('Hello World'); } ~~~ 上面代碼省略了for語句表達式的三個部分,結果就導致了一個無限循環。 (3)do...while循環 do...while循環與while循環類似,唯一的區別就是先運行一次循環體,然后判斷循環條件。 ~~~ do statement while(expression); // 或者 do { statement } while(expression); ~~~ 不管條件是否為真,do..while循環至少運行一次,這是這種結構最大的特點。另外,while語句后面的分號不能省略。 (4)break語句和continue語句 break語句和continue語句都具有跳轉作用,可以讓代碼不按既有的順序執行。 break語句用于跳出代碼塊或循環。 ~~~ var i = 0; while (i<100){ console.log('i當前為:' + i); i++; if (i === 10) break; } ~~~ 上面代碼只會執行10次循環,一旦i等于10,就會跳出循環。 continue語句用于立即終止本次循環,返回循環結構的頭部,開始下一次循環。 ~~~ var i = 0; while (i<100){ i++; if (i%2===0) continue; console.log('i當前為:' + i); } ~~~ 上面代碼只有在i為奇數時,才會輸出i的值。如果i為偶數,則直接進入下一輪循環。 如果存在多重循環,不帶參數的break語句和continue語句都只針對最內層循環。 (5)標簽(label) JavaScript語言允許,語句的前面有標簽(label)。標簽通常與break語句和continue語句配合使用,跳出特定的循環。 ~~~ top: for (var i=0;i<3;i++){ for (var j=0;j<3;j++){ if (i===1 && j===1) break top; console.log("i="+i+",j="+j); } } // i=0,j=0 // i=0,j=1 // i=0,j=2 // i=1,j=0 ~~~ 上面代碼為一個雙重循環區塊,加上了top標簽(注意,top不用加引號)。當滿足一定條件時,使用break語句加上標簽名,直接跳出雙層循環。如果break語句后面不使用標簽,則只能跳出內層循環,進入下一次的外層循環。 continue語句也可以與標簽配合使用。 ~~~ top: for (var i=0;i<3;i++){ for (var j=0;j<3;j++){ if (i===1 && j===1) continue top; console.log("i="+i+",j="+j); } } // i=0,j=0 // i=0,j=1 // i=0,j=2 // i=1,j=0 // i=2,j=0 // i=2,j=1 // i=2,j=2 ~~~ 上面代碼在滿足一定條件時,使用continue語句加上標簽名,直接進入下一輪外層循環。如果continue語句后面不使用標簽,則只能進入下一輪的內層循環。 ## 數據類型 ### 概述 JavaScript語言的每一個值,都屬于某一種數據類型。JavaScript的數據類型,共有六個類別和兩個特殊值。 六個類別的數據類型又可以分成兩組:原始類型(primitive type)和合成類型(complex type)。 原始類型包括三種數據類型。 * 數值(number) * 字符串(string) * 布爾值(boolean) “數值”就是整數和小數(比如1和3.14),“字符串”就是由多個字符組成的文本(比如"Hello World"),“布爾值”則是true(真)和false(假)兩個特定值。 合成類型也包括三種數據類型。 * 對象(object) * 數組(array) * 函數(function) 對象和數組是兩種不同的數據組合方式,而函數其實是處理數據的方法。JavaScript把函數當成一種數據類型,可以像其他類型的數據一樣,進行賦值和傳遞,這為編程帶來了很大的靈活性,體現了JavaScript作為“函數式語言”的本質。 這里需要明確的是,JavaScript的所有數據,都可以視為對象。不僅合成類型的數組和函數屬于對象的特例,就連原始類型的數據(數值、字符串、布爾值)也可以用對象方式調用。 除了上面這六個類別,JavaScript還定義了兩個特殊值null和undefined。 本書將分別詳細介紹這六個類別和兩個特殊值。其中,兩個特殊值和布爾類型比較簡單,將在本節介紹,其他類型將各自有單獨的一節。 ### typeof運算符 JavaScript有三種方法,可以確定一個值到底是什么類型。 * typeof運算符 * instanceof運算符 * Object.prototype.toString方法 instanceof運算符和Object.prototype.toString方法,將在后文相關章節介紹。這里著重介紹typeof 運算符。 typeof運算符可以返回一個值的數據類型,可能有以下結果。 (1)原始類型 數值、字符串、布爾值分別返回number、string、boolean。 ~~~ typeof 123 // "number" typeof "123" // "string" typeof false // "boolean" ~~~ (2)函數 函數返回function。 ~~~ // 定義一個空函數 function f(){} typeof f // "function" ~~~ (3)undefined undefined返回undefined。 ~~~ typeof undefined // "undefined" ~~~ 利用這一點,typeof可以用來檢查一個沒有聲明的變量,而不報錯。 ~~~ v // ReferenceError: v is not defined typeof v // "undefined" ~~~ 實際編程中,這個特點通常用在判斷語句。 ~~~ // 錯誤的寫法 if (v){ // ... } // ReferenceError: v is not defined // 正確的寫法 if (typeof v === "undefined"){ // ... } ~~~ (4)其他 除此以外,都返回object。 ~~~ typeof window // "object" typeof {} // "object" typeof [] // "object" typeof null // "object" ~~~ 從上面代碼可以看到,空數組([])的類型也是object,這表示在JavaScript內部,數組本質上只是一種特殊的對象。另外,null的類型也是object,這是由于歷史原因造成的,為了兼容以前的代碼,后來就沒法修改了,并不是說null就屬于對象,本質上null是一個類似于undefined的特殊值。 既然typeof對數組(array)和對象(object)的顯示結果都是object,那么怎么區分它們呢?instanceof運算符可以做到。 ~~~ var o = {}; var a = []; o instanceof Array // false a instanceof Array // true ~~~ instanceof運算符的詳細解釋,請見《面向對象編程》一章。 ### null和undefined (1)相似性 首先,null與undefined都可以表示“無”,含義非常相似。將一個變量賦值為undefined或null,老實說,幾乎沒區別。 ~~~ var a = undefined; // 或者 var a = null; ~~~ 上面代碼中,a變量分別被賦值為undefined和null,這兩種寫法幾乎等價。 在if語句中,都會被自動轉為false,相等運算符甚至直接報告兩者相等。 ~~~ if (!undefined) console.log('undefined is false'); // undefined is false if (!null) console.log('null is false'); // null is false undefined == null // true ~~~ 上面代碼說明,兩者的行為是何等相似!Google公司開發的JavaScript語言的替代品Dart語言,就明確規定只有null,沒有undefined! 既然含義與用法都差不多,為什么要同時設置兩個這樣的值,這不是無端增加復雜度,令初學者困擾嗎?這與歷史原因有關。 (2)歷史原因 1995年JavaScript誕生時,最初像Java一樣,只設置了null作為表示"無"的值。根據C語言的傳統,null被設計成可以自動轉為0。 ~~~ Number(null) // 0 5 + null // 5 ~~~ 但是,JavaScript的設計者Brendan Eich,覺得這樣做還不夠,有兩個原因。 首先,null像在Java里一樣,被當成一個對象。但是,JavaScript的數據類型分成原始類型和合成類型兩大類,Brendan Eich覺得表示"無"的值最好不是對象。 其次,JavaScript的最初版本沒有包括錯誤處理機制,發生數據類型不匹配時,往往是自動轉換類型或者默默地失敗。Brendan Eich覺得,如果null自動轉為0,很不容易發現錯誤。 因此,Brendan Eich又設計了一個undefined。他是這樣區分的:null是一個表示"無"的對象,轉為數值時為0;undefined是一個表示"無"的原始值,轉為數值時為NaN。 ~~~ Number(undefined) // NaN 5 + undefined // NaN ~~~ 但是,這樣的區分在實踐中很快就被證明不可行。目前,null和undefined基本是同義的,只有一些細微的差別。 (3)用法和含義 對于null和undefined,可以大致上像下面這樣理解。 null表示"沒有對象",即該處不應該有值。典型用法是: * 作為函數的參數,表示該函數的參數不是對象。 * 作為對象原型鏈的終點。 undefined表示"缺少值",就是此處應該有一個值,但是還未定義。典型用法是: * 變量被聲明了,但沒有賦值時,就等于undefined。 * 調用函數時,應該提供的參數沒有提供,該參數等于undefined。 * 對象沒有賦值的屬性,該屬性的值為undefined。 * 函數沒有返回值時,默認返回undefined。 ~~~ var i; i // undefined function f(x){console.log(x)} f() // undefined var o = new Object(); o.p // undefined var x = f(); x // undefined ~~~ (4)null的特殊之處 null的特殊之處在于,JavaScript把它包含在對象類型(object)之中。 ~~~ typeof null // "object" ~~~ 上面代碼表示,查詢null的類型,JavaScript返回object(對象)。 這并不是說null的數據類型就是對象,而是JavaScript早期部署中的一個約定俗成,其實不完全正確,后來再想改已經太晚了,會破壞現存代碼,所以一直保留至今。 (5)注意點 JavaScript的標識名區分大小寫,所以undefined和null不同于Undefined和Null(或者其他僅僅大小寫不同的詞形),后者只是普通的變量名。 ### 布爾值 布爾值代表“真”和“假”兩個狀態。“真”用關鍵字true表示,“假”用關鍵字false表示。布爾值只有這兩個值。 下列運算符會返回布爾值: * 兩元邏輯運算符: && (And),|| (Or) * 前置邏輯運算符: ! (Not) * 相等運算符:===,!==,==,!= * 比較運算符:>,>=,<,<= 如果JavaScript預期某個位置應該是布爾值,會將該位置上現有的值自動轉為布爾值。轉換規則是除了下面六個值被轉為false,其他值都視為true。 * undefined * null * false * 0 * NaN * ""(空字符串) 布爾值往往用于程序流程的控制,請看一個例子。 ~~~ if (""){ console.log(true);} // 沒有任何輸出 ~~~ 上面代碼的if命令后面的判斷條件,預期應該是一個布爾值,所以JavaScript自動將空字符串,轉為布爾值false,導致程序不會進入代碼塊,所以沒有任何輸出。 需要特別注意的是,空數組([])和空對象({})對應的布爾值,都是true。 ~~~ if ([]){ console.log(true);} // true if ({}){ console.log(true);} // true ~~~ 更多關于數據類型轉換的介紹,參見《數據類型轉換》一節。 ## 結尾的分號 ### 不使用分號結尾的語句 分號表示一條語句的結尾。但是,有一些語法結構不需要在語句的結尾添加分號,主要是以下三種情況。 (1)for和while循環 ~~~ for(;;){} // 沒有分號 while(true){} // 沒有分號 ~~~ 需要注意的是do...while循環是有分號的。 ~~~ do { a--; } while(a > 0); // 分號不能省略 ~~~ (2)分支語句:if, switch, try ~~~ if (true) {} // 沒有分號 switch () {} // 沒有分號 try {} catch {} // 沒有分號 ~~~ (3)函數的聲明語句 ~~~ function f() {} // 沒有分號 ~~~ 但是函數表達式仍然要使用分號。 ~~~ var f = function f() {}; ~~~ 以上三種情況,如果使用了分號,并不會出錯。因為,解釋引擎會把這個分號解釋為空語句。 ### 分號的自動添加 除了本來就不寫分號的情況,JavaScript引擎還有一個特點,就是在應該寫分號卻沒寫的情況下,它會自動添加(Automatic Semicolon Insertion,簡稱ASI)。 ~~~ var a = b + c // 等同于 var a = b + c; ~~~ 但是,這種自動添加不是絕對的。如果下一行的開始可以與本行的結尾連在一起解釋,就不會自動添加分號。 ~~~ var a = 3 // 等同于 var a = 3; "abc" .length // 等同于 "abc".length ~~~ 上面代碼舉了兩個例子,每行的尾部都沒有分號,JavaScript并不會自動添加分號,因為每行的結尾與下一行的開頭可以放在一起解釋。下面這個例子也不會自動添加分號。 ~~~ 3 * (2 * (4 + (3 - 5))) + (10 * (27 / 6)) // 等同于 3 * (2 * (4 + (3 - 5))) + (10 * (27 / 6)) ~~~ 這些例子還是比較容易看出來的,但是下面的例子就不那么容易發現了。它們都不會自動添加分號。 ~~~ var a = b + c (d+e).toString(); /* 結果報錯,因為兩行連在一起, 解釋為c(d+e), 即對函數 c 的調用 */ a = b /hi/g.exec(c).map(d); /* 解釋為 a = b / hi / g.exec(c).map(d), 即把正則表達式的斜杠當作除法運算符 */ var a = "b" [ "red", "green" ].forEach(function(c) { console.log(c) }) /* 結果報錯,因為兩行連在一起, 解釋為"b"["red", "green"], 即把字符串當作一個數組,按索引取值 */ var a = 0; var f = function(x) { return x } (a++) /* f等于0,因為(a++)被 * 視為匿名函數的調用 */ return a + b; return (a + b) obj.foo(arg1, arg2) ~~~ 一般來說,在沒有分號結尾的情況下,如果下一行起首的是(、 [ 、+、-、/這五個字符中的一個,分號不會被自動添加。只有下一行的開始與本行的結尾,無法放在一起解釋,JavaScript引擎才會自動添加分號。 ~~~ if (a < 0) a = 0 console.log(a) // 等同于下面的代碼, // 因為0console沒有意義 if (a < 0) a = 0; console.log(a) ~~~ 另外,如果一行的起首是“自增”(++)或“自減”(--)運算符,則它們的前面會自動添加分號。 ~~~ a = b = c = 1 a ++ b -- c console.log(a, b, c) // 1 2 0 ~~~ 之所以會得到“1 2 0”的結果,原因是自增和自減運算符前,自動被加上了分號。上面的代碼實際上等同于下面的形式: ~~~ a = b = c = 1; a; ++b; --c; ~~~ 如果continue、break、return和throw這四個語句后面,直接跟換行符,則會自動添加分號。這意味著,如果return語句返回的是一個對象的字面量,起首的大括號一定要寫在同一行,否則得不到預期結果。 ~~~ return { first: "Jane" }; // 解釋成 return; { first: "Jane" }; ~~~ 由于解釋引擎自動添加分號的行為難以預測,因此編寫代碼的時候不應該省略行尾的分號。 省略結尾的分號,還有一個問題。有些JavaScript代碼壓縮器不會自動添加分號,因此遇到沒有分號的結尾,就會讓代碼保持原狀,而不是壓縮成一行。 ## 參考鏈接 * Axel Rauschmayer,?[A quick overview of JavaScript](http://www.2ality.com/2011/10/javascript-overview.html) * Axel Rauschmayer,?[Improving the JavaScript typeof operator](http://www.2ality.com/2011/11/improving-typeof.html) * Axel Rauschmayer,?[Automatic semicolon insertion in JavaScript](http://www.2ality.com/2011/05/semicolon-insertion.html) * Axel Rauschmayer,?[Categorizing values in JavaScript](http://www.2ality.com/2013/01/categorizing-values.html) * Rod Vagg,?[JavaScript and Semicolons](http://dailyjs.com/2012/04/19/semicolons/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看