最近與部門老大一塊兒面試了許多前端求職者,其中想換個學習氛圍較好的人佔多數,但良好的學習氛圍也是須要一點點營造出來的🌺。javascript
爲此咱們組建了咱們團隊內部的「現代 JavaScript 突擊隊」,第一期學習內容爲《現代 JavaScript 教程》系列,幫助小組成員系統地進行學習鞏固,並讓你們養成系統性學習和輸出學習總結的學習方式。html
本文做爲我輸出的第一部分學習總結,但願做爲一份自測清單,幫助你們鞏固知識,溫故知新。前端
這裏也下面分享咱們學習小組的「押金制度」和「押金記錄表」🍀java
接下來開始分享自測清單的內容。git
JavaScript 腳本引入方式有兩種:es6
<script>
標籤插入腳本;<script>
標籤 src
設置腳本地址。<script>
標籤有如下經常使用屬性:github
src
:指定外部腳本的URI, 若是設置了 src
特性,script 標籤內容將會被忽略;面試
<script src="example-url.js"></script>
type
:指定引用腳本的語言,屬性值爲 MIME 類型,包括text/javascript
, text/ecmascript
, application/javascript
, 和application/ecmascript
。若是沒有定義這個屬性,腳本會被視做JavaScript。express
ES6 新增了屬性值 module
,代碼會被當作 JavaScript 模塊。編程
<script type="text/javascript"></script>
async
規定一旦腳本可用,則會異步執行。
注意:async 屬性僅適用於外部腳本(只有在使用 src 屬性時)。
有多種執行外部腳本的方法:
若是 async="async"
:腳本相對於頁面的其他部分異步地執行(當頁面繼續進行解析時,腳本將被執行);
若是不使用 async
且 defer="defer"
:腳本將在頁面完成解析時執行;
若是既不使用 async
也不使用 defer
:在瀏覽器繼續解析頁面以前,當即讀取並執行腳本;
<script async="async"></script>
defer
屬性規定是否對腳本執行進行延遲,直到頁面加載爲止。
若是您的腳本不會改變文檔的內容,可將 defer 屬性加入到 <script>
標籤中,以便加快處理文檔的速度。由於瀏覽器知道它將可以安全地讀取文檔的剩餘部分而不用執行腳本,它將推遲對腳本的解釋,直到文檔已經顯示給用戶爲止。
<script defer="defer"></script>
詳細介紹能夠閱讀《MDN <script>
章節 》。
語句是執行行爲(action)的語法結構和命令。如: alert('Hello, world!')
這樣能夠用來顯示消息的語句。
存在分行符時,多數狀況下能夠省略分號。但不全是,好比:
alert(3 + 1 + 2);
建議新人最好不要省略分號。
單行註釋以兩個正斜槓字符 //
開始。
// 註釋文本 console.log("leo");
多行註釋以一個正斜槓和星號開始 「/*」
並以一個星號和正斜杆結束 「*/」
。
/* 這是多行註釋。 第二行註釋。 */ console.log("leo");
JavaScript 的嚴格模式是使用受限制的 JavaScript 的一種方式,從而隱式地退出「草率模式」。
"use strict"
指令將瀏覽器引擎轉換爲「現代」模式,改變一些內建特性的行爲。
經過在腳本文件/函數開頭添加 "use strict";
聲明,便可啓用嚴格模式。
全局開啓嚴格模式:
// index.js "use strict"; const v = "Hi! I'm a strict mode script!";
函數內開啓嚴格模式:
// index.js function strict() { 'use strict'; function nested() { return "And so am I!"; } return "Hi! I'm a strict mode function! " + nested(); }
"use strict"
須要定義在腳本最頂部(函數內除外),不然嚴格模式可能沒法啓用。啓用 "use strict"
後,爲未定義元素賦值將拋出異常:
"use strict"; leo = 17; // Uncaught ReferenceError: leo is not defined
啓用 "use strict"
後,試圖刪除不可刪除的屬性時會拋出異常:
"use strict"; delete Object.prototype; // Uncaught TypeError: Cannot delete property 'prototype' of function Object() { [native code] }
詳細介紹能夠閱讀《MDN 嚴格模式章節 》。
變量是數據的「命名存儲」。
目前定義變量可使用三種關鍵字:var / let / const。三者區別能夠閱讀《let 和 const 命令》 。
let name = "leo"; let name = "leo", age, addr; let name = "leo", age = 27, addr = "fujian";
變量命名有 2 個限制:
$
和 _
。變量命名還有一些建議:
const PI = 3.141592
;userName
或者 shoppingCart
。leo
與 Leo
是不一樣的;let 平安 = "leo"
;a
、b
、c
這種縮寫。JavaScript 是一種弱類型或者說動態語言。這意味着你不用提早聲明變量的類型,在程序運行過程當中,類型會被自動肯定。這也意味着你可使用同一個變量保存不一樣類型的數據:
var foo = 42; // foo is a Number now foo = "bar"; // foo is a String now foo = true; // foo is a Boolean now
詳細介紹能夠閱讀《MDN JavaScript 數據類型和數據結構 》。
前七種爲基本數據類型,也稱爲原始類型(值自己沒法被改變),而 object
爲複雜數據類型。
八大數據類型分別是:
number
用於任何類型的數字:整數或浮點數,在 ±2 範圍內的整數。bigint
用於任意長度的整數。string
用於字符串:一個字符串能夠包含一個或多個字符,因此沒有單獨的單字符類型。boolean
用於 true
和 false
。null
用於未知的值 —— 只有一個 null
值的獨立類型。undefined
用於未定義的值 —— 只有一個 undefined
值的獨立類型。symbol
用於惟一的標識符。object
用於更復雜的數據結構。每一個類型後面會詳細介紹。
經過 typeof
運算符檢查:
typeof x
或者 typeof(x)
。"string"
。typeof null
會返回 "object"
—— 這是 JavaScript 編程語言的一個錯誤,實際上它並非一個 object
。typeof "leo" // "string" typeof undefined // "undefined" typeof 0 // "number" typeof NaN // "number" typeof 10n // "bigint" typeof true // "boolean" typeof Symbol("id") // "symbol" typeof [1,2,3,4] // "object" typeof Math // "object" (1) Math 是一個提供數學運算的內建 object。 typeof null // "object" (2) JavaScript 語言的一個錯誤,null 不是一個 object。null 有本身的類型,它是一個特殊值。 typeof alert // "function" (3) alert 在 JavaScript 語言中是一個函數。
JavaScript 變量能夠轉換爲新變量或其餘數據類型:
經過全局方法 String()
將其餘類型數據(任何類型的數字,字母,布爾值,對象)轉換爲 String 類型:
String(123); // "123" // Number方法toString()/toExponential()/toFixed()/toPrecision() 也有一樣效果。 String(false); // "false" // Boolean方法 toString() 也有一樣效果。 String(new Date()); // "Sun Jun 07 2020 21:44:20 GMT+0800 (中國標準時間)" // Date方法 toString() 也有一樣效果。 String(leo);
經過如下幾種方式能將其餘類型數據轉換爲 Number 類型:
+
const age = +"22"; // 22
Number
方法const age = Number("22"); // 22 Number.parseFloat("22"); // 22 Number.parseInt("22"); // 22
// 布爾值 Number(false) // 返回 0 Number(true) // 返回 1 // 日期 const date = new Date(); Number(date); // 返回 1591537858154 date.getTime(); // 返回 1591537858154,效果一致。 // 自動轉換 5 + null // 返回 5 null 轉換爲 0 "5" + null // 返回"5null" null 轉換爲 "null" "5" + 1 // 返回 "51" 1 轉換爲 "1" "5" - 1 // 返回 4 "5" 轉換爲 5
轉換規則以下:
0
、空字符串、null
、undefined
和 NaN
)將變爲 false
。true
。Boolean(1); // true Boolean(0); // false Boolean("hello"); // true Boolean(""); // false Boolean("0"); // true Boolean(" "); // 空白, 也是 true (任何非空字符串是 true)
常見運算符如加法 +
、減法 -
、乘法 *
和除法 /
,舉一個例子,來介紹一些概念:
let sum = 1 + 2; let age = +18;
其中:
1 + 2
中, 1
和 2
爲 2 個運算元,左運算元 1
和右運算元 2
,即運算元就是運算符做用的對象。 1 + 2
運算式中包含 2 個運算元,所以也稱該運算式中的加號 +
爲 二元運算符。 +18
中的加號 +
對應只有一個運算元,則它是 一元運算符 。let msg = "hello " + "leo"; // "hello leo" let total = 10 + 20; // 30 let text1 = "1" + "2"; // "12" let text2 = "1" + 2; // "12" let text3 = 1 + "2"; // "12" let text4 = 1 + 2 + "3"; // "33" let num = +text1; // 12 轉換爲 Number 類型
運算符的優先級決定了表達式中運算執行的前後順序,優先級高的運算符最早被執行。
下面的表將全部運算符按照優先級的不一樣從高(20)到低(1)排列。
優先級 | 運算類型 | 關聯性 | 運算符 | ||
---|---|---|---|---|---|
20 | 圓括號 |
n/a(不相關) | ( … ) |
||
19 | 成員訪問 |
從左到右 | … . … |
||
需計算的成員訪問 |
從左到右 | … [ … ] |
|||
new (帶參數列表) |
n/a | new … ( … ) |
|||
函數調用 | 從左到右 | … ( … ) |
|||
可選鏈(Optional chaining) | 從左到右 | ?. |
|||
18 | new (無參數列表) | 從右到左 | new … |
||
17 | 後置遞增(運算符在後) | n/a | |||
… ++ |
|||||
後置遞減(運算符在後) | … -- |
||||
16 | 邏輯非 | 從右到左 | ! … |
||
按位非 | ~ … |
||||
一元加法 | + … |
||||
一元減法 | - … |
||||
前置遞增 | ++ … |
||||
前置遞減 | -- … |
||||
typeof | typeof … |
||||
void | void … |
||||
delete | delete … |
||||
await | await … |
||||
15 | 冪 | 從右到左 | … ** … |
||
14 | 乘法 | 從左到右 | |||
… * … |
|||||
除法 | … / … |
||||
取模 | … % … |
||||
13 | 加法 | 從左到右 | |||
… + … |
|||||
減法 | … - … |
||||
12 | 按位左移 | 從左到右 | … << … |
||
按位右移 | … >> … |
||||
無符號右移 | … >>> … |
||||
11 | 小於 | 從左到右 | … < … |
||
小於等於 | … <= … |
||||
大於 | … > … |
||||
大於等於 | … >= … |
||||
in | … in … |
||||
instanceof | … instanceof … |
||||
10 | 等號 | 從左到右 | |||
… == … |
|||||
非等號 | … != … |
||||
全等號 | … === … |
||||
非全等號 | … !== … |
||||
9 | 按位與 | 從左到右 | … & … |
||
8 | 按位異或 | 從左到右 | … ^ … |
||
7 | 按位或 | 從左到右 | `… | …` | |
6 | 邏輯與 | 從左到右 | … && … |
||
5 | 邏輯或 | 從左到右 | `… | …` | |
4 | 條件運算符 | 從右到左 | … ? … : … |
||
3 | 賦值 | 從右到左 | … = … |
||
… += … |
|||||
… -= … |
|||||
… *= … |
|||||
… /= … |
|||||
… %= … |
|||||
… <<= … |
|||||
… >>= … |
|||||
… >>>= … |
|||||
… &= … |
|||||
… ^= … |
|||||
`… | = …` | ||||
2 | yield | 從右到左 | yield … |
||
yield* | yield* … |
||||
1 | 展開運算符 | n/a | ... … |
||
0 | 逗號 | 從左到右 | … , … |
3 > 2 && 2 > 1 // return true 3 > 2 > 1 // 返回 false,由於 3 > 2 是 true,而且 true > 1 is false // 加括號能夠更清楚:(3 > 2) > 1
在 JS 中的值的比較與數學很類型:
a>b
/ a<b
/ a>=b
/ a<=b
;// 使用 ==,非嚴格等於,不關心值類型 // == 運算符會對比較的操做數作隱式類型轉換,再比較 '1' == 1; // true // 使用 ===,嚴格相等,關心值類型 // 將數字值 -0 和 +0 視爲相等,並認爲 Number.NaN 不等於 NaN。 '1' === 1; // false
(圖片來自:《MDN JavaScript 中的相等性判斷》)
和判斷相等同樣,也有兩種: !=
/ !==
。
另外 ES6 新增 Object.is 方法判斷兩個值是否相同,語法以下:
Object.is(value1, value2);
如下任意項成立則兩個值相同:
使用示例:
Object.is('foo', 'foo'); // true Object.is(window, window); // true Object.is('foo', 'bar'); // false Object.is([], []); // false var foo = { a: 1 }; var bar = { a: 1 }; Object.is(foo, foo); // true Object.is(foo, bar); // false Object.is(null, null); // true // 特例 Object.is(0, -0); // false Object.is(0, +0); // true Object.is(-0, -0); // true Object.is(NaN, 0/0); // true
兼容性 Polyfill 處理:
if (!Object.is) { Object.is = function(x, y) { // SameValue algorithm if (x === y) { // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 return x !== 0 || 1 / x === 1 / y; } else { // Step 6.a: NaN == NaN return x !== x && y !== y; } }; }
對於相等性判斷比較簡單:
null == undefined; // true null === undefined; // false
對於其餘比較,它們會先轉換位數字:null
轉換爲 0
, undefied
轉換爲 NaN
。
null > 0; // false 1 null >= 0; // true 2 null == 0; // false 3 null < 1; // true 4
須要注意:null == 0; // false
這裏是由於:undefined
和 null
在相等性檢查 ==
中不會進行任何的類型轉換,它們有本身獨立的比較規則,因此除了它們之間互等外,不會等於任何其餘的值。
undefined > 0; // false 1 undefined > 1; // false 2 undefined == 0; // false 3
第 一、2 行都返回 false
是由於 undefined
在比較中被轉換爲了 NaN
,而 NaN
是一個特殊的數值型值,它與任何值進行比較都會返回 false
。
第 3 行返回 false
是由於這是一個相等性檢查,而 undefined
只與 null
相等,不會與其餘值相等。
顯示一個警告對話框,上面顯示有指定的文本內容以及一個「肯定」按鈕。
注意:彈出模態框,並暫停腳本,直到用戶點擊「肯定」按鈕。
// 語法 window.alert(message); alert(message); // 示例 alert('hello leo!');
message
是要顯示在對話框中的文本字符串,若是傳入其餘類型的值,會轉換成字符串。
顯示一個對話框,對話框中包含一條文字信息,用來提示用戶輸入文字。
注意:彈出模態框,並暫停腳本,直到用戶點擊「肯定」按鈕。
當點擊肯定返回文本,點擊取消或按下 Esc 鍵返回 null
。
語法以下:
let result = window.prompt(text, value);
result
用來存儲用戶輸入文字的字符串,或者是 null。text
用來提示用戶輸入文字的字符串,若是沒有任何提示內容,該參數能夠省略不寫。value
文本輸入框中的默認值,該參數也能夠省略不寫。不過在 Internet Explorer 7 和 8 中,省略該參數會致使輸入框中顯示默認值"undefined"。Window.confirm()
方法顯示一個具備一個可選消息和兩個按鈕(肯定和取消)的模態對話框。
注意:彈出模態框,並暫停腳本,直到用戶點擊「肯定」按鈕。
語法以下:
let result = window.confirm(message);
當 if 語句當條件表達式,會將表達式轉換爲布爾值,當爲 truthy 時執行裏面代碼。
轉換規則如:
0
、空字符串 ""
、null
、undefined
和 NaN
都會被轉換成 false
。由於他們被稱爲 「falsy」 值。true
,因此它們被稱爲 「truthy」。條件(三元)運算符是 JavaScript 僅有的使用三個操做數的運算符。一個條件後面會跟一個問號(?),若是條件爲 truthy ,則問號後面的表達式A將會執行;表達式A後面跟着一個冒號(:),若是條件爲 falsy ,則冒號後面的表達式B將會執行。本運算符常常做爲 [if](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else)
語句的簡捷形式來使用。
語法:
condition ? exprIfTrue : exprIfFalse
計算結果用做條件的表達式。
若是表達式 condition 的計算結果是 truthy(它和 true 相等或者能夠轉換成 true ),那麼表達式 exprIfTrue 將會被求值。
若是表達式 condition 的計算結果是 falsy(它能夠轉換成 false ),那麼表達式 exprIfFalse 將會被執行。
示例:
let getUser = function(name){ return name === 'leo' ? 'hello leo!' : 'unknow user'; } // 能夠簡寫以下: let getUser = name => name === 'leo' ? 'hello leo!' : 'unknow user'; getUser('leo'); // "hello leo!" getUser('pingan'); // "unknow user"
詳細能夠閱讀《MDN 邏輯運算符》 。
邏輯運算符以下表所示 (其中_expr_
多是任何一種類型, 不必定是布爾值):
運算符 | 語法 | 說明 | ||||
---|---|---|---|---|---|---|
邏輯與,AND(&& ) |
_expr1_ && _expr2_ |
若 expr**1** 可轉換爲 true ,則返回 expr**2** ;不然,返回 expr**1** 。 |
||||
邏輯或,OR(` | `) | `_expr1_ | _expr2_` | 若 expr**1** 可轉換爲 true ,則返回 expr**1** ;不然,返回 expr**2** 。 |
||
邏輯非,NOT(! ) |
!_expr_ |
若 expr 可轉換爲 true ,則返回 false ;不然,返回 true 。 |
若是一個值能夠被轉換爲 true
,那麼這個值就是所謂的 truthy,若是能夠被轉換爲 false
,那麼這個值就是所謂的 falsy。
會被轉換爲 false
的表達式有:
null
;NaN
;0
;""
or ''
or `
`);undefined
。儘管 &&
和 ||
運算符可以使用非布爾值的操做數, 但它們依然能夠被看做是布爾操做符,由於它們的返回值老是可以被轉換爲布爾值。若是要顯式地將它們的返回值(或者表達式)轉換爲布爾值,請使用雙重非運算符(即!!
)或者Boolean構造函數。
JavaScript 裏有三個邏輯運算符:||
(或),&&
(與),!
(非)。
全部條件都爲 true 才返回 true,不然爲 false。
a1 = true && true // t && t 返回 true a2 = true && false // t && f 返回 false a3 = false && true // f && t 返回 false a4 = false && (3 == 4) // f && f 返回 false a5 = "Cat" && "Dog" // t && t 返回 "Dog" a6 = false && "Cat" // f && t 返回 false a7 = "Cat" && false // t && f 返回 false a8 = '' && false // f && f 返回 "" a9 = false && '' // f && f 返回 false
全部條件有一個爲 true 則返回 true,不然爲 false。
o1 = true || true // t || t 返回 true o2 = false || true // f || t 返回 true o3 = true || false // t || f 返回 true o4 = false || (3 == 4) // f || f 返回 false o5 = "Cat" || "Dog" // t || t 返回 "Cat" o6 = false || "Cat" // f || t 返回 "Cat" o7 = "Cat" || false // t || f 返回 "Cat" o8 = '' || false // f || f 返回 false o9 = false || '' // f || f 返回 ""
n1 = !true // !t 返回 false n2 = !false // !f 返回 true n3 = !'' // !f 返回 true n4 = !'Cat' // !t 返回 false
n1 = !!true // !!truthy 返回 true n2 = !!{} // !!truthy 返回 true: 任何 對象都是 truthy 的… n3 = !!(new Boolean(false)) // …甚至 .valueOf() 返回 false 的布爾值對象也是! n4 = !!false // !!falsy 返回 false n5 = !!"" // !!falsy 返回 false n6 = !!Boolean(false) // !!falsy 返回 false
condi1 && confi2 // 轉換爲 !(!condi1 || !condi2)
condi1 || condi2 // 轉換爲 !(!condi1 && !condi2)
因爲邏輯表達式的運算順序是從左到右,也能夠用如下規則進行"短路"計算:
(some falsy expression) && (_expr)_
短路計算的結果爲假。(some truthy expression) || _(expr)_
短路計算的結果爲真。短路意味着上述表達式中的expr部分不會被執行,所以expr的任何反作用都不會生效(舉個例子,若是expr是一次函數調用,此次調用就不會發生)。形成這種現象的緣由是,整個表達式的值在第一個操做數被計算後已經肯定了。看一個例子:
function A(){ console.log('called A'); return false; } function B(){ console.log('called B'); return true; } console.log( A() && B() ); // logs "called A" due to the function call, // then logs false (which is the resulting value of the operator) console.log( B() || A() ); // logs "called B" due to the function call, // then logs true (which is the resulting value of the operator)
與運算 &&
的優先級比或運算 ||
要高。
因此代碼 a && b || c && d
徹底跟 &&
表達式加了括號同樣:(a && b) || (c && d)
。
詳細能夠閱讀《MDN while》 。
while 語句能夠在某個條件表達式爲真的前提下,循環執行指定的一段代碼,直到那個表達式不爲真時結束循環。
如:
var n = 0; var x = 0; while (n < 3) { n++; x += n; }
當循環體爲單行時,能夠不寫大括號:
let i = 3; while(i) console.log(i --);
詳細能夠閱讀《MDN do...while》 。do...while
語句建立一個執行指定語句的循環,直到condition
值爲 false。在執行statement
後檢測condition
,因此指定的statement
至少執行一次。
如:
var result = ''; var i = 0; do { i += 1; result += i + ' '; } while (i < 5);
詳細能夠閱讀《MDN for》 。for
語句用於建立一個循環,它包含了三個可選的表達式,這三個表達式被包圍在圓括號之中,使用分號分隔,後跟一個用於在循環中執行的語句(一般是一個塊語句)。
語法如:
for (begin; condition; step) { // ……循環體…… }
示例:
for (let i = 0; i < 3; i++) { console.log(i); }
描述:
begin | i = 0 |
進入循環時執行一次。 |
---|---|---|
condition | i < 3 |
在每次循環迭代以前檢查,若是爲 false,中止循環。 |
body(循環體) | alert(i) |
條件爲真時,重複運行。 |
step | i++ |
在每次循環體迭代後執行。 |
for
語句頭部圓括號中的全部三個表達式都是可選的。
var i = 0; for (; i < 3; i++) { console.log(i); }
for (var i = 0;; i++) { console.log(i); if (i > 3) break; }
var i = 0; for (;;) { if (i > 3) break; console.log(i); i++; }
詳細能夠閱讀《MDN break》 。
break 語句停止當前循環,switch
語句或label
語句,並把程序控制流轉到緊接着被停止語句後面的語句。
在 while 語句中:
function testBreak(x) { var i = 0; while (i < 6) { if (i == 3) { break; } i += 1; } return i * x; }
另外,也能夠爲代碼塊作標記,並在 break 中指定要跳過的代碼塊語句的 label:
outer_block:{ inner_block:{ console.log ('1'); break outer_block; // breaks out of both inner_block and outer_block console.log (':-('); // skipped } console.log ('2'); // skipped }
須要注意的是:break 語句須要內嵌在它所應用的標籤或代碼塊中,不然報錯:
block_1:{ console.log ('1'); break block_2; // SyntaxError: label not found } block_2:{ console.log ('2'); }
continue 聲明終止當前循環或標記循環的當前迭代中的語句執行,並在下一次迭代時繼續執行循環。
與 break
語句的區別在於, continue 並不會終止循環的迭代,而是:
注意:continue 也必須在對應循環內部,不然報錯。
i = 0; n = 0; while (i < 5) { i++; if (i === 3) { continue; } n += i; }
帶 label:
var i = 0, j = 8; checkiandj: while (i < 4) { console.log("i: " + i); i += 1; checkj: while (j > 4) { console.log("j: "+ j); j -= 1; if ((j % 2) == 0) continue checkj; console.log(j + " is odd."); } console.log("i = " + i); console.log("j = " + j); }
禁止 break/continue
在 ‘?’ 的右邊:
(i > 5) ? console.log(i) : continue; // continue 不容許在這個位置
這樣會提示語法錯誤。
請注意非表達式的語法結構不能與三元運算符 ?
一塊兒使用。特別是 break/continue
這樣的指令是不容許這樣使用的。
三種循環:
while
—— 每次迭代以前都要檢查條件。do..while
—— 每次迭代後都要檢查條件。for (;;)
—— 每次迭代以前都要檢查條件,可使用其餘設置。一般使用 while(true)
來構造「無限」循環。這樣的循環和其餘循環同樣,均可以經過 break
指令來終止。
若是咱們不想在當前迭代中作任何事,而且想要轉移至下一次迭代,那麼可使用 continue
指令。break/continue
支持循環前的標籤。標籤是 break/continue
跳出嵌套循環以轉到外部的惟一方法。
switch
語句用來將表達式的值與 case 語句匹配,並執行與狀況對應的語句。switch
語句能夠替代多個 if 判斷,爲多個分支選擇的狀況提供一個更具描述性的方式。
switch
語句至少包含一個 case
代碼塊和一個可選的 default
代碼塊:
switch(expression) { case 'value1': // do something ... [break] default: // ... [break] }
當 expression
表達式的值與 value1
匹配時,則執行其中代碼塊。
若是沒有 case
子句匹配,則會選擇 default
子句執行,若連 default
子句都沒有,則直接執行到 switch
結束。
所謂 case 分組,就是與多個 case 分支共享同一段代碼,以下面例子中 case 1
和 case 2
:
let a = 2; switch (a) { case 1: // (*) 下面這兩個 case 被分在一組 case 2: console.log('case is 1 or 2!'); break; case 3: console.log('case is 3!'); break; default: console.log('The result is default.'); } // 'case is 1 or 2!'
expression
表達式的值與 case
值的比較是嚴格相等:function f(n){ let a ; switch(n){ case 1: a = 'number'; break; case '1': a = 'string'; break; default: a = 'default'; break; } console.log(a) } f(1); // number f('1'); // string
break
,程序將不通過任何檢查就會繼續執行下一個 **case**
:let a = 2 + 2; switch (a) { case 3: console.log( 'Too small' ); case 4: console.log( 'Exactly!' ); case 5: console.log( 'Too big' ); default: console.log( "I don't know such values" ); } // Exactly! // Too big // I don't know such values
**default**
放在 **case**
之上不影響匹配: function f(n){ switch (n) { case 2: console.log(2); break; default: console.log('default') break; case 1: console.log('1'); break; } } f(1); // 1 f(2); // 2 f(3); // default
switch
語句中存在 let
/ const
重複聲明問題:// 如下定義會報錯 function f(n){ switch(n){ case 1: let msg = 'hello'; console.log(1); break; case 2: let msg = 'leo'; break; default: console.log('default'); break; } } // Error: Uncaught SyntaxError: Identifier 'msg' has already been declared
這是因爲兩個 let
處於同一個塊級做用域,因此它們被認爲是同一變量名的重複聲明。
解決方式,只須要將 case
語句包裝在括號內便可解決:
function f(n){ switch(n){ case 1:{ // added brackets let msg = 'hello'; console.log(msg); break; } case 2: { let msg = 'leo'; console.log(msg); break; } default: console.log('default'); break; } }
函數可讓一段代碼被屢次調用,避免重複代碼。
如以前學習到的一些內置函數: alert(msg)
/ prompt(msg, default)
/ confirm(quesyion)
等。
定義函數有兩種方式:函數聲明和函數表達式。
如定義一個簡單 getUser
函數:
function getUser(name){ return 'hello ' + name; } getUser('leo"); // 函數調用
經過函數聲明來定義函數時,須要由如下幾部分組成:
getUser
;name
;return 'hello ' + name
。相似聲明變量,仍是以 getUser
爲例:
let getUser = function(name){ return 'hello ' + name; }
另外,函數表達式也能夠提供函數名,並用於函數內部指代函數自己:
let fun = function f(n){ return n < 3 ? 1 : n * f(n - 1); } fun(3); // 3 fun(5); // 60
當定義一個函數後,它並不會自動執行,而是須要使用函數名稱進行調用,如上面例子:
fun(3); // 3
只要注意:
使用 函數表達式 定義函數時,調用函數的方法必須寫在定義以後,不然報錯:
console.log(fun()); // Uncaught ReferenceError: fun is not defined let fun = function(){return 1};
而使用 函數聲明 則不會出現該問題:
console.log(fun()); // 1 function fun(){return 1};
緣由就是:函數提高僅適用於函數聲明,而不適用於函數表達式。
在函數中,可使用局部變量和外部變量。
函數中聲明的變量只能在該函數內可見。
let fun = function(){ let name = 'leo'; } fun(); console.log(name); // Uncaught ReferenceError: name is not defined
函數內可使用外部變量,而且能夠修改外部變量的值。
let name = 'leo'; let fun = function(){ let text = 'Hello, ' + name; console.log(text); } fun(); // Hello, leo
當函數內也有與外部變量名稱相同的變量,會忽略外部變量:
let name = 'leo'; let fun = function(){ let name = 'pingan8787'; let text = 'Hello, ' + name; console.log(text); } fun(); // Hello, pingan8787
從ECMAScript 6開始,有兩個新的類型的參數:默認參數,剩餘參數。
若函數沒有傳入參數,則參數默認值爲undefined
,一般設置參數默認值是這樣作的:
// ES6 以前,沒有設置默認值 function f(a, b){ b = b ? b : 1; return a * b; } f(2,3); // 6 f(2); // 2 // ES6,設置默認值 function f(a, b = 1){ return a * b; } f(2,3); // 6 f(2); // 2
能夠將參數中不肯定數量的參數表示成數組,以下:
function f (a, ...b){ console.log(a, b); } f(1,2,3,4); // a => 1 b => [2, 3, 4]
既然講到參數,那就不能少了 arguments 對象。
函數的實際參數會被保存在一個相似數組的arguments對象中。在函數內,咱們可使用 arguments 對象獲取函數的全部參數:
let fun = function(){ console.log(arguments); console.log(arguments.length); } fun('leo'); // Arguments ["leo", callee: ƒ, Symbol(Symbol.iterator): ƒ] // 1
以一個實際示例介紹,實現將任意數量參數鏈接成一個字符串,並輸出的函數:
let argumentConcat = function(separator){ let result = '', i; for(i = 1; i < arguments.length; i ++){ result += arguments[i] + separator; } return result; } argumentConcat(',', 'leo', 'pingan'); //"leo,pingan,"
在函數任意位置,指定 return
指令來中止函數的執行,並返回函數指定的返回值。
let sum = function(a, b){ return a + b; }; let res = sum(1, 2); console.log(res); // 3
默認空值的 return
或沒有 return
的函數返回值爲 undefined
。
函數表達式是一種函數定義方式,在前面章節中已經介紹到了,這個部分將着重介紹 函數表達式 和 函數聲明 的區別:
// 函數表達式 let fun = function(){}; // 函數聲明 function fun(){}
函數表達式會在代碼執行到達時被建立,而且僅從那一刻可用。
而函數聲明被定義以前,它就能夠被調用。
// 函數表達式 fun(); // Uncaught ReferenceError: fun is not defined let fun = function(){console.log('leo')}; // 函數聲明 fun(); // "leo" function fun(){console.log('leo')};
建議優先考慮函數聲明語法,它可以爲組織代碼提供更多靈活性,由於咱們能夠在聲明函數前調用該函數。
本章節簡單介紹箭頭函數基礎知識,後面章節會完整介紹。
函數箭頭表達式是ES6新增的函數表達式的語法,也叫胖箭頭函數,變化:更簡潔的函數和this
。
// 有1個參數 let f = v => v; // 等同於 let f = function (v){return v}; // 有多個參數 let f = (v, i) => {return v + i}; // 等同於 let f = function (v, i){return v + i}; // 沒參數 let f = () => 1; // 等同於 let f = function (){return 1}; let arr = [1,2,3,4]; arr.map(ele => ele + 1); // [2, 3, 4, 5]
this
;new
實例化;arguments
對象,即不能使用,可使用rest
參數代替;yield
命令,即不能用做Generator函數。一個簡單的例子:
function Person(){ this.age = 0; setInterval(() => { this.age++; }, 1000); } var p = new Person(); // 定時器一直在執行 p的值一直變化
本文做爲《初中級前端 JavaScript 自測清單》第一部分,介紹的內容以經常使用基礎知識爲主,並在學習資料中,將知識點結合實際開發中遇到的場景進行展開介紹。但願能幫助你們自測本身的 JavaScript 水平並查缺補漏,溫故知新。
Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推薦 | https://github.com/pingan8787... |
ES小冊 | js.pingan8787.com |
語雀知識庫 | Cute-FrontEnd |