<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 6.語法 > 原文: [http://exploringjs.com/impatient-js/ch_syntax.html](http://exploringjs.com/impatient-js/ch_syntax.html) > > 貢獻者:[Hunter-liu](https://github.com/lq920320) ### 6.1. JavaScript 語法概述 #### 6.1.1. 基本語法 注釋: ```javascript // 單行注釋 ``` ```javascript /* 多行 注釋 */ ``` *原始*(原子)值: ```javascript // Booleans true false // Numbers (JavaScript 的數字只有一種類型) -123 1.414 // String (JavaScript 的字符沒有對應的類型) 'abc' "abc" ``` *斷言*描述了計算結果的預期結果,如果這些期望不正確則拋出異常。例如,以下斷言聲明計算 7 加 1 的結果必須為 8: ```javascript assert.equal(7 + 1, 8); ``` `assert.equal()`是一個方法調用(對象是`assert`,方法是`.equal()`),有兩個參數:實際結果和預期結果。它是 Node.js 斷言 API 的一部分,本書后面的[將對此進行解釋](/docs/10.md)。 打印日志到[瀏覽器的控制臺](/docs/7.md#531瀏覽器控制臺)或 Node.js: ```javascript // 將值標準輸出打印(另一種方法調用) console.log("Hello!"); ``` ```javascript // 將錯誤信息標準輸出打印 console.error('Something weng wrong!'); ``` 運算符: ```javascript // 布爾運算符 assert.equal(true && false, false); // 與 assert.equal(true || false, true); // 或 // 數學運算符 assert.equal(3 + 4, 7); assert.equal(5 - 1, 4); assert.equal(3 * 4, 12); assert.equal(9 / 3, 3); // 字符串操作符 assert.equal('a' + 'b', 'ab'); assert.equal('I see ' + 3 + ' monkeys', 'I see 3 monkeys'); // 比較運算符 assert.equal(3 < 4, true); assert.equal(3 <= 4, true); assert.equal('abc' === 'abc', true); assert.equal('abc' !== 'def', true); ``` 聲明變量: ```javascript let x; // 聲明 x(可變的) x = 3 * 5; // 給 x 賦值 let y = 3 * 5; // 聲明變量并為其賦值 const z = 8; // 聲明 y(不可變的) ``` 控制流聲明: ```javascript // 條件語句 if (x < 0) { // x 小于 0? x = -x; } ``` 普通函數聲明: ```javascript // add1() 有 a 和 b 兩個參數 function add1(a, b) { return a + b; } // 調用函數 add1() assert.equal(add1(5, 2), 7); ``` 箭頭函數表達式(特別用作函數調用和方法調用的參數): ```javascript const add2 = (a, b) => a + b; // 調用方法 add2() assert.equal(add2(5, 2), 7); const add3 = (a, b) => { return a + b }; ``` 上面的代碼包含以下箭頭函數(關于*表達式*和*語句塊*等術語將在在[本章后面解釋](/docs/8.md#64-語句與表達)): ```javascript // 主體為一個表達式的箭頭函數 (a, b) => a + b // 主體為一個代碼塊的箭頭函數 (a, b) => { return a + b } ``` 對象: ```javascript // 通過 object 符號({})創建一個對象 const obj = { first: 'Jane', // 屬性 last: 'Doe', // 屬性 getFullName() { // 屬性(方法) return this.first + ' ' + this.last; }, }; // 獲取某個屬性值 assert.equal(obj.first, 'Jane'); // 設置某個屬性的值 obj.first = 'Janey'; // 調用對象的方法 assert.equal(obj.getFullName(), 'Janey Doe'); ``` 數組(數組也是對象): ```javascript // 通過 Array 符號([])創建一個數組 const arr = ['a', 'b', 'c']; // 獲取某個數組元素 assert.equal(arr[1], 'b'); // 設置某個數組元素的值 arr[1] = 'β'; ``` #### 6.1.2. 模塊 每個模塊都是一個文件。例如,考慮以下兩個包含模塊的文件: ```js file-tools.js main.js ``` `file-tools.js`中的模塊導出其功能`isTextFilePath()`: ```js export function isTextFilePath(filePath) { return filePath.endsWith('.txt'); } ``` `main.js`中的模塊導入整個模塊`path`和函數`isTextFilePath()`: ```js // 導入整個模塊 `path` import * as path from 'path'; // 導入模塊 file-tools.js export的一個函數 import {isTextFilePath} from './file-tools.js'; ``` #### 6.1.3. 法定變量和屬性名稱 變量名稱和屬性名稱的語法類別稱為*標識符*。 標識符允許具有以下字符: - Unicode 字母:`A` - `Z`,`a` - `z`(等) - `$`,`_` - Unicode 數字:`0` - `9`(等) - 變量名不能以數字開頭 有些單詞在 JavaScript 中有特殊含義,稱為*保留字*。例如:`if`,`true`,`const`。 保留字不能用作變量名: ```js const if = 123; // SyntaxError: Unexpected token if ``` 但它們被允許作為屬性的名稱: ``` > const obj = { if: 123 }; > obj.if 123 ``` #### 6.1.4. 連接類型 用于連接單詞的常見類型是: - 駝峰:`threeConcatenatedWords` - 下劃線(也稱*蛇形*):`three_concatenated_words` - 分隔線(也稱*串形*):`three-concatenated-words` #### 6.1.5. 命名大寫 通常,JavaScript 使用駝峰大小寫,但常量除外。 小寫: - 函數,變量:`myFunction` - 方法:`obj.myMethod` - CSS: - CSS 實體:`special-class` - 對應的 JavaScript 變量:`specialClass` 大寫: - 類名:`MyClass` - 常數:`MY_CONSTANT` - 常量也常用駱駝寫成:`myConstant` #### 6.1.6. 在哪里加分號? 在語句的最后: ```js const x = 123; func(); ``` 但是,如果該語句以大括號結尾,那就不加分號了: ```js while (false) { // ··· } // 無分號 function func() { // ··· } // 無分號 ``` 但是,在這樣的語句之后添加分號不是語法錯誤 - 它被解釋為空語句: ```js // 函數聲明后跟空語句 function func() { // ··· }; ``` ![](https://img.kancloud.cn/ff/a8/ffa8e16628cad59b09c786b836722faa.svg) **測驗:基本** 參見[測驗應用程序](/docs/11.md#91測驗)。 ### 6.2. (深入) 本章的所有其余部分都是深入說明(上面的內容)。 ### 6.3. 身份標識 #### 6.3.1. 有效標識符(變量名等) 首字符: - Unicode 字母(包括`é`和`ü`等重音字符和非拉丁字母的字符,如`α`) - `$` - `_` 后續字符: - 合法的首字符 - Unicode 數字(包括東方阿拉伯數字) - 一些其他 Unicode 標記和標點符號 例如: ```js const ε = 0.0001; const строка = ''; let _tmp = 0; const $foo2 = true; ``` #### 6.3.2. 保留字 保留字不能是變量名,但它們可以是屬性名。 所有 JavaScript *關鍵字*都是保留字: > `await` `break` `case` `catch` `class` `const` `continue` `debugger` `default` `delete` `do` `else` `export` `extends` `finally` `for` `function` `if` `import` `in` `instanceof` `let` `new` `return` `static` `super` `switch` `this` `throw` `try` `typeof` `var` `void` `while` `with` `yield` 以下標記也是關鍵字,但目前未在該語言中使用: > `enum` `implements` `package` `protected` `interface` `private` `public` 以下值是保留字: > `true` `false` `null` 從技術上講,這些單詞不是保留的,但你也應該避免使用它們,因為它們實際上是關鍵字: > `Infinity` `NaN` `undefined` `async` 您也不應將全局變量的名稱(`String`,`Math`等)用于您自己的變量和參數。 ### 6.4. 語句與表達 在本節中,我們將探討 JavaScript 如何區分兩種句法結構:_ 語句 _ 和 _ 表達式 _。之后,我們會發現這會導致問題,因為相同的語法可能意味著不同的東西,具體取決于它的使用位置。 ![](https://img.kancloud.cn/7b/17/7b17729df07100ffa1c582a9b46ac13a.svg) **我們假裝只有語句和表達** 為簡單起見,我們假裝 JavaScript 中只有語句和表達式。 #### 6.4.1. 語句 *語句* 是一段可以執行并執行某種操作的代碼。例如,`if`是一段語句: ```js let myStr; if (myBool) { myStr = 'Yes'; } else { myStr = 'No'; } ``` 語句的另一個例子:函數聲明。 ```js function twice(x) { return x + x; } ``` #### 6.4.2. 表達式 *表達式*是可以*評估*以產生值的一段代碼。例如,括號之間的代碼是一個表達式: ```js let myStr = (myBool ? 'Yes' : 'No'); ``` 括號之間使用的運算符 `_?_:_` 稱為*三元運算符*。它是`if`語句的表達式版本。 讓我們看一下表達式的更多例子。我們輸入表達式,REPL 為我們評估它們: ``` > 'ab' + 'cd' 'abcd' > Number('123') 123 > true || false true ``` #### 6.4.3. 什么是允許的? JavaScript 源代碼中的當前位置決定了您可以使用哪種語法結構: - 函數體必須是一系列語句: ```js function max(x, y) { if (x > y) { return x; } else { return y; } } ``` - 函數調用或方法調用的參數必須是表達式: ```js console.log('ab' + 'cd', Number('123')); ``` 但是,表達式可以用作語句。然后將它們稱為*表達式語句*。相反的情況并非如此:當上下文需要表達式時,你便不能使用語句。 以下代碼演示了某個表達式`bar()`可以是表達式還是語句——它取決于上下文: ```js console.log(bar()); bar(); ``` ### 6.5. 語法模糊 JavaScript 有幾種語法歧義的編程結構:相同的語法被不同地解釋,這取決于它是在語句上下文中還是在表達式上下文中使用。本節探討了這一現象及其引發的陷阱。 #### 6.5.1. 相同的語法:函數聲明和函數表達式 *函數聲明*是一個聲明: ```js function id(x) { return x; } ``` *函數表達式*是一個表達式(`=`右側的): ```js const id = function me(x) { return x; }; ``` #### 6.5.2. 相同的語法:object literal 和 block 在下面的代碼中,`{}`是 *對象字面值*:一個創建空對象的表達式。 ```js const obj = {}; ``` 這是一個空代碼塊(聲明): ```js { } ``` #### 6.5.3. 消除歧義 歧義只是語句上下文中的一個問題:如果 JavaScript 解析器遇到模糊語法,它不知道它是簡單語句還是表達式語句。例如: - 如果語句以`function`開頭:它是函數聲明還是函數表達式? - 如果語句以`{`開頭:它是對象字面值還是代碼塊? 為了解決歧義,以`function`或`{`開頭的語句永遠不會被解釋為表達式。如果希望表達式語句以這些標記中的任何一個開頭,則必須將其包裝在括號中: ```js (function (x) { console.log(x) })('abc'); // Output: // 'abc' ``` 在這段代碼中: 1. 我們首先通過函數表達式創建一個函數: ```js function (x) { console.log(x) } ``` 1. 然后我們調用該函數:`('abc')` #1 只被解釋為表達式,因為我們將它包裝在括號中。如果我們沒有,我們會得到一個語法錯誤,因為 JavaScript 需要一個函數聲明,之后還會警告缺少的函數名稱。此外,你不能在函數聲明后立即進行函數調用。 在本書的后面,我們將看到更多由語法模糊引起的陷阱的例子: * [通過對象解構分配](/docs/41.md#3443語法陷阱通過對象解構分配) * [從箭頭函數](/docs/28.md#23333語法陷阱從箭頭函數返回一個對象字面值) ### 6.6. 分號 #### 6.6.1. 分號的經驗法則 每個語句都以分號結束。 ```js const x = 3; someFunction('abc'); i++; ``` 例外:以塊結尾的語句。 ```js function foo() { // ··· } if (y > 0) { // ··· } ``` 以下情況有點棘手: ```js const func = () => {}; // 分號! ``` 整個`const`聲明(一個語句)以分號結尾,但在其中,有一個箭頭函數表達式。那就是:聲明本身并不是以花括號結尾;它是嵌入式箭頭函數表達式。這就是為什么最后會有一個分號的原因。 #### 6.6.2. 分號:控制語句 控制語句的主體本身就是一個聲明。例如,這是`while`循環的語法: ```js while (condition) 語句 ``` 正文可以是一行語句: ```js while (a > 0) a--; ``` 但代碼塊也是聲明,因此也是控制聲明的合法主體: ```js while (a > 0) { a--; } ``` 如果你想讓一個循環有一個空的主體,那么你的首選便是一個空語句(它只是一個分號): ```js while (processNextItem() > 0); ``` 你的第二個選擇是一個空語句塊: ```js while (processNextItem() > 0) {} ``` ### 6.7. 自動分號插入(ASI) 雖然我建議總是寫分號,但大多數都是 JavaScript 中的可選項。使這成為可能的機制稱為*自動分號插入*(ASI)。在某種程度上,它可以糾正語法錯誤。 ASI 的工作原理如下。語句解析會直到出現以下情況: - 分號 - 行終止符后跟非法標記 換句話說,ASI 可以看作在換行符處插入分號。接下來的小節將介紹 ASI 的陷阱。 #### 6.7.1. ASI 意外觸發 關于 ASI 的好消息是——如果你不依賴它并且總是寫分號——你只需要注意一個陷阱。這是 JavaScript 禁止在一些標記之后的換行符。如果插入換行符,也會插入分號。 最實際相關的標記是`return`。例如,考慮以下代碼: ```js return { first: 'jane' }; ``` 此代碼解析為: ```js return; { first: 'jane'; } ; ``` 也就是說,一個空的 return 語句,后跟一個代碼塊,后跟一個空語句。 為什么 JavaScript 會這樣做?它可以防止在`return`之后意外返回一行中的值。 #### 6.7.2. ASI 意外沒有觸發 在某些情況下,當您認為 ASI 應該觸發時,ASI *并沒有觸發*。對于那些不喜歡分號的人來說,這會使生活更加復雜,因為他們需要意識到這些情況。以下是三個例子。還有更多。 **例 1:**非預期的函數調用。 ```js a = b + c (d + e).print() ``` 解析為: ```js a = b + c(d + e).print(); ``` **例 2:**意外分裂。 ```js a = b /hi/g.exec(c).map(d) ``` 解析為: ```js a = b / hi / g.exec(c).map(d); ``` **例 3:**非預期的屬性訪問。 ```js someFunction() ['ul', 'ol'].map(x => x + x) ``` 被執行為: ```js const propKey = ('ul','ol'); assert.equal(propKey, 'ol'); // 因為逗號 someFunction()[propKey].map(x => x + x); ``` ### 6.8. 分號:最佳實踐 我建議你要經常寫分號: - 我喜歡它提供代碼的視覺結構——你清楚地看到一個語句何時結束。 - 要記住的規則較少。 - 大多數 JavaScript 程序員使用分號。 然而,也有許多人不喜歡添加分號的視覺混亂。如果你是其中之一:可能會認為沒有它們的代碼*亦是*合法的。我建議你使用工具來幫助您避免錯誤。以下是兩個例子: - 自動代碼格式化程序 [Prettier](https://prettier.io) 可以配置為不使用分號。然后它會自動修復問題。例如,如果它遇到以方括號開頭的行,則它以分號為前綴。 - 靜態檢查器 [ESLint](https://eslint.org) 有一套你可以表述你的首選樣式的[規則](https://eslint.org/docs/rules/semi)(始終使用分號或盡可能少的分號),并向你對關鍵問題報警。 ### 6.9. 嚴格模式 從 ECMAScript 5 開始,你可以選擇在所謂的*嚴格模式*中執行 JavaScript。在該模式下,語言稍微清晰:不存在一些怪異的寫法并且同時會拋出更多異常。 默認(非嚴格)模式也稱為*草率模式*。 請注意,默認模式在模塊和類中默認打開,因此在編寫現代 JavaScript(幾乎總是位于模塊中)時,您并不需要了解它。在本書中,我假設嚴格模式始終打開。 #### 6.9.1. 開啟嚴格模式 在舊腳本文件和 CommonJS 模塊中,通過將以下代碼放在第一行中,您可以為完整文件切換嚴格模式: ```js 'use strict'; ``` 關于這個“指令”的巧妙之處在于,5 之前的 ECMAScript 版本只是忽略它:它是一個什么都不做的表達式語句。 你還可以僅為單個函數打開嚴格模式: ``` function functionInStrictMode() { 'use strict'; } ``` #### 6.9.2. 示例:嚴格模式 讓我們看一個示例,其中草率模式做一些嚴格模式不會做的壞事:更改未知變量(未通過`let`或類似創建)創建一個全局變量。 ```js function sloppyFunc() { unknownVar1 = 123; } sloppyFunc(); // Created global variable `unknownVar1`: assert.equal(unknownVar1, 123); ``` 嚴格模式則做得更好: ```js function strictFunc() { 'use strict'; unknownVar2 = 123; } assert.throws( () => strictFunc(), { name: 'ReferenceError', message: 'unknownVar2 is not defined', }); ``` `assert.throws()`要求它的第一個參數,某個函數,在調用時拋出`ReferenceError`。 ![](https://img.kancloud.cn/ff/a8/ffa8e16628cad59b09c786b836722faa.svg) **測驗:高級** 參見[測驗應用程序](/docs/11.md#91測驗)。
                  <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>

                              哎呀哎呀视频在线观看