現代JavaScript 之JavaScript 基礎知識(第一部分 第二章) 易錯總結

在這裏插入圖片描述

(現代JavaScript 之JavaScript 基礎知識 第一部分 第二章 易錯總結)

2.1 Hello, world!

1. 現代 JavaScript 中已經不這樣使用了。這些註釋是用於不支持 <script> 標籤的古老的瀏覽器隱藏 JavaScript 代碼的。由於最近 15 年內發佈的瀏覽器都沒有這樣的問題,因此這種註釋能幫你辨認出一些老掉牙的代碼。

 <script type=…> <script language=…>

2. 一個單獨的 &lt;script&gt;標籤不能同時有 src 特性和內部包裹的代碼。

<script src="file.js">
  alert(1); // 此內容會被忽略,因爲設定了 src
</script>

2.2 代碼結構

1. 在大多數的編輯器中,一行代碼可以使用<kbd>Ctrl+/</kbd> 熱鍵進行單行註釋,<kbd> Ctrl+Shift+/ </kbd>的熱鍵可以進行多行註釋
2. 不要在 /*...*/ 內嵌套另一個 /*...*/

2.3 現代模式,"use strict"

1. 沒有辦法取消 "use strict"沒有類似於 "no use strict" 這樣的指令可以使程序返回默認模式。一旦進入了嚴格模式,就沒有回頭路了。
2. 當你使用 開發者控制檯 運行代碼時,請注意它默認是不啓動 "use strict" 的。你可以嘗試搭配使用 <kbd>Shift+Enter</kbd> 按鍵去輸入多行代碼,然後將 "use strict" 放在代碼最頂部。
3. 目前我們歡迎將 "use strict"; 寫在腳本的頂部。稍後,當你的代碼全都寫在了 class 和 module 中時,你則可以將 "use strict"; 這行代碼省略掉。

2.4 變量

1. var 關鍵字與 let 大體 相同,也用來聲明變量,但稍微有些不同,也有點“老派”。
2. 額外聲明一個變量絕對是利大於弊的。現代的 JavaScript 壓縮器和瀏覽器都能夠很好地對代碼進行優化,所以不會產生性能問題。爲不同的值使用不同的變量可以幫助引擎對代碼進行優化。

2.5 數據類型

8 種基本的數據類型

  • Number 類型
    特殊數值:Infinity-InfinityNaN,數學運算是安全的
  • BigInt 類型
    “number” 類型無法表示大於 (253-1)(即 9007199254740991),或小於 -(253-1) 的整數。這是其內部表示形式導致的技術限制。可以通過將 n 附加到整數字段的末尾來創建 BigInt 值。
  • String 類型
    反引號:let phrase = ``can embed another ${str}``;
  • Boolean 類型(邏輯類型)
    用於 true 和 false。
  • “null” 值
    JavaScript 中的 null 僅僅是一個代表“無”、“空”或“值未知”的特殊值。
  • “undefined” 值
    undefined 的含義是 未被賦值。如果一個變量已被聲明,但未被賦值,那麼它的值就是 undefined
  • object 類型
    用於更復雜的數據結構。
  • symbol 類型
    用於唯一的標識符。

typeof 運算符

  • 兩種形式:typeof x 或者 typeof(x)。
  • typeof null 會返回 "object" —— 這是 JavaScript 編程語言的一個錯誤,實際上它並不是一個 object。

2.6 交互:alert、prompt 和 confirm

alert

alert("Hello");

彈出的帶有信息的小窗口被稱爲 模態窗
prompt

result = prompt(title, [default]);
    title 顯示給用戶的文本
    default 可選的第二個參數,指定 input 框的初始值。(不是必須的)

confirm

result = confirm(question);

點擊確定返回 true,點擊取消返回 false

2.7 類型轉換

字符串轉換

字符串轉換最明顯。false 變成 "false",null 變成 "null" 等。
數字型轉換

變成……
undefined NaN
null 0
true 和 false 1 and 0
string 去掉首尾空格後的純數字字符串中含有的數字。如果剩餘字符串爲空,則轉換結果爲 0。否則,將會從剩餘字符串中“讀取”數字。當類型轉換出現 error 時返回 NaN。

請注意 nullundefined 在這有點不同:null 變成數字 0undefined 變成 NaN
布爾型轉換
轉換規則如下:

  • 直觀上爲“空”的值(如 0、空字符串、null、undefined 和 NaN)將變爲 false。
  • 其他值變成 true。
  • 對 "0" 和只有空格的字符串(比如:" ")進行布爾型轉換時,輸出結果爲 true。

請注意:包含 0 的字符串 "0" 是 true

2.8 基礎運算符,數學

數字轉化,一元運算符 +

但是如果運算元不是數字,加號 + 則會將其轉化爲數字。

// 轉化非數字
alert( +true ); // 1
alert( +"" );   // 0

2.9 值的比較

一個有趣的現象

let a = 0;
alert( Boolean(a) ); // false

let b = "0";
alert( Boolean(b) ); // true

alert(a == b); // true!

對 null 和 undefined 進行比較

當使用嚴格相等 === 比較二者時

它們不相等,因爲它們屬於不同的類型。

alert( null === undefined ); // false

當使用非嚴格相等 == 比較二者時

JavaScript 存在一個特殊的規則,會判定它們相等。它們倆就像“一對戀人”,僅僅等於對方而不等於其他任何的值(只在非嚴格相等下成立)。

alert( null == undefined ); // true

當使用數學式或其他比較方法 < > <= >= 時:

null/undefined 會被轉化爲數字:null 被轉化爲 0,undefined 被轉化爲 NaN。

alert( null > 0 );  // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true

特立獨行的 undefined

alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)

值的比較練習題

5 > 4 → true
"apple" > "pineapple" → false
"2" > "12" → true
undefined == null → true
undefined === null → false
null == "\n0\n" → false
null === +"\n0\n" → false

2.11 邏輯運算符

||(或)

result = value1 || value2 || value3;

一個或運算 || 的鏈,將返回第一個真值,如果不存在真值,就返回該鏈的最後一個值。

&&(與)

result = value1 && value2 && value3;

與運算返回第一個假值,如果沒有假值就返回最後一個值。
與運算 && 的優先級比或運算 || 要高。

!(非)

兩個非運算 !! 有時候用來將某個值轉化爲布爾類型:

alert( !!"non-empty string" ); // true
alert( !!null ); // false

下面的代碼將會輸出什麼?

alert( alert(1) || 2 || alert(3) );

答案:首先是 1,然後是 2.

與運算連接的 alerts 的結果是什麼?

alert( alert(1) && alert(2) );

答案:1,然後 undefined。

或運算、與運算、或運算串聯的結果

alert( null || 2 && 3 || 4 );

答案:3。

2.12 空值合併運算符 '??'

a ?? b 的結果是:

  • 如果 a 是已定義的,則結果爲 a,
  • 如果 a 不是已定義的,則結果爲 b。

重寫 result = a ?? b

result = (a !== null && a !== undefined) ? a : b;

舉例


let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// 顯示第一個已定義的值:
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder

與 || 比較

它們之間重要的區別是:

  • || 返回第一個 值。
  • ?? 返回第一個 已定義的 值。

如果沒有明確添加括號,不能將其與 || 或 && 一起使用。

2.13 循環:while 和 for

普通 break 只會打破內部循環
標籤 是在循環之前帶有冒號的標識符:

outer: for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    let input = prompt(`Value at coords (${i},${j})`, '');
    // 如果是空字符串或被取消,則中斷並跳出這兩個循環。
    if (!input) break outer; // (*)
    // 用得到的值做些事……
  }
}

我們還可以將標籤移至單獨一行:

outer:
for (let i = 0; i < 3; i++) { ... }

continue 指令也可以與標籤一起使用。在這種情況下,執行跳轉到標記循環的下一次迭代。

只有在循環內部才能調用 break/continue,並且標籤必須位於指令上方的某個位置。

break label;  // 無法跳轉到這個標籤
label: for (...)

易錯題
以下兩個循環的 alert 值是否相同?

前綴形式 ++i: 從 1 到 4

let i = 0;
while (++i < 5) alert( i );

後綴形式 i++:從 1 到 5

let i = 0;
while (i++ < 5) alert( i );

2.14 "switch" 語句

共享同一段代碼的幾個 case 分支可以被分爲一組:

let a = 3;
switch (a) {
  case 4:
    alert('Right!');
    break;

  case 3: // (*) 下面這兩個 case 被分在一組
  case 5:
    alert('Wrong!');
    alert("Why don't you take a math class?");
    break;

  default:
    alert('The result is strange. Really.');
}

2.15 函數

默認值

如果未提供參數,那麼其默認值則是 undefined。

如果我們想在本示例中設定“默認”的 text,那麼我們可以在 = 之後指定它:

function showMessage(from, text = "no text given") {
  alert( from + ": " + text );
}
showMessage("Ann"); // Ann: no text given

這裏 "no text given" 是一個字符串,但它可以是更復雜的表達式,並且只會在缺少參數時纔會被計算和分配。所以,這也是可能的:

function showMessage(from, text = anotherFunction()) {
  // anotherFunction() 僅在沒有給定 text 時執行
  // 其運行結果將成爲 text 的值
}

後備的默認參數
我們可以拿它跟 undefined 做比較:

function showMessage(text) {
  if (text === undefined) {
    text = 'empty message';
  }
  alert(text);
}
showMessage(); // empty message

我們可以使用 || 運算符:

// 如果 "text" 參數被省略或者被傳入空字符串,則賦值爲 'empty'
function showMessage(text) {
  text = text || 'empty';
  ...
}

現代 JavaScript 引擎支持 空值合併運算符 ??,當可能遇到其他假值時它更有優勢,如 0 會被視爲正常值不被合併:


// 如果沒有傳入 "count" 參數,則顯示 "unknown"
function showCount(count) {
  alert(count ?? "unknown");
}

showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown

空值的 return 或沒有 return 的函數返回值爲 undefined

函數命名

函數以 XX 開始……

  • "get…" —— 返回一個值,
  • "calc…" —— 計算某些內容,
  • "create…" —— 創建某些內容,
  • "check…" —— 檢查某些內容並返回 boolean 值,等。

2.16 函數表達式

在 JavaScript 中,函數不是“神奇的語言結構”,而是一種特殊的值。

函數聲明:

function sayHi() {
  alert( "Hello" );
}

函數表達式:

let sayHi = function() {
  alert( "Hello" );
};

我們可以複製函數到其他變量:

function sayHi() {   // (1) 創建
  alert( "Hello" );
}

let func = sayHi;    // (2) 複製

func(); // Hello     // (3) 運行復制的值(正常運行)!
sayHi(); // Hello    //     這裏也能運行(爲什麼不行呢)

爲什麼這裏末尾會有個分號?

function sayHi() {
  // ...
}
let sayHi = function() {
  // ...
};
  • 在代碼塊的結尾不需要加分號 ;,像 if { ... },for { },function f { } 等語法結構後面都不用加。
  • 函數表達式是在語句內部的:let sayHi = ...;,作爲一個值。它不是代碼塊而是一個賦值語句。不管值是什麼,都建議在語句末尾添加分號 ;。所以這裏的分號與函數表達式本身沒有任何關係,它只是用於終止語句。

回調函數

function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

function showOk() {
  alert( "You agreed." );
}

function showCancel() {
  alert( "You canceled the execution." );
}

// 用法:函數 showOk 和 showCancel 被作爲參數傳入到 ask
ask("Do you agree?", showOk, showCancel);

ask 的兩個參數值 showOk 和 showCancel 可以被稱爲 回調函數 或簡稱 回調。

函數表達式 vs 函數聲明

函數表達式是在代碼執行到達時被創建,並且僅從那一刻起可用。

一旦代碼執行到賦值表達式 let sum = function… 的右側,此時就會開始創建該函數,並且可以從現在開始使用(分配,調用等)。

函數聲明則不同。

在函數聲明被定義之前,它就可以被調用。

一個全局函數聲明對整個腳本來說都是可見的,無論它被寫在這個腳本的哪個位置。

函數聲明的另外一個特殊的功能是它們的塊級作用域。

嚴格模式下,當一個函數聲明在一個代碼塊內時,它在該代碼塊內的任何位置都是可見的。但在代碼塊外不可見。

如果我們使用函數聲明,則以下代碼無法像預期那樣工作:

let age = prompt("What is your age?", 18);
// 有條件地聲明一個函數
if (age < 18) {
  function welcome() {
    alert("Hello!");
  }
} else {
  function welcome() {
    alert("Greetings!");
  }
}
// ……稍後使用
welcome(); // Error: welcome is not defined

正確的做法是使用函數表達式,並將 welcome 賦值給在 if 外聲明的變量,並具有正確的可見性。

下面的代碼可以如願運行:

let age = prompt("What is your age?", 18);
let welcome;
if (age < 18) {
  welcome = function() {
    alert("Hello!");
  };
} else {
  welcome = function() {
    alert("Greetings!");
  };
}
welcome(); // 現在可以了

2.17 箭頭函數,基礎知識

單行箭頭函數

let func = (arg1, arg2, ...argN) => expression

多行的箭頭函數

let sum = (a, b) => {  // 花括號表示開始一個多行函數
  let result = a + b;
  return result; // 如果我們使用了花括號,那麼我們需要一個顯式的 “return”
};
alert( sum(1, 2) ); // 3

2.18 JavaScript 特性

typeof 運算符返回值的類型,但有兩個例外:

    typeof null == "object" // JavaScript 編程語言的設計錯誤
    typeof function(){} == "function" // 函數被特殊對待

值 null 和 undefined 是特殊的:它們只在 == 下相等,且不相等於其他任何值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章