一、ES6 基本認識
1、什么是 ES6?
ES6 指的是 ECMAScript 6.0,是JavaScript 語言的一個標準,其目標是使JavaScript 可以用來撰寫復雜的大型的應用程式,成為企業級開發的語言,
2、ES6 與 JavaScript 的區別?
ES6 是 JavaScript 的一個標準,JavaScript 是 ES6 的具體實作,
3、Babel 轉碼器?
Babel 是一個被廣泛使用的 ES6 轉碼器,其可以將 ES6 代碼轉為 ES5 代碼,從而在現有環境下執行,即使用 ES6 撰寫代碼而無需擔心不能運行,
簡單的講就是 一些 瀏覽器 不支持 ES6 部分語法,可以使用 Babel 轉碼器將 ES6 語法 轉為 ES5 語法,從而被 瀏覽器 識別,
比如:
ES6 可以使用 箭頭函式來 替代 普通函式,通過 Babel 轉碼器,可以將 箭頭函式 轉為 普通函式,這樣就不需要去擔心瀏覽器是否支持這種語法,
【ES6】 input.map(item => item + 1); 【ES5】 input.map(function (item) { return item + 1; });
二、常用特性
1、let 命令
(1)基本內容
let 命令通常用來宣告區域變數,
特性:區域有效、不存在變數提升、暫時性死區、不允許重復宣告,
(2)特性一:區域有效,
let 命令類似于 var,用來宣告變數,但是 var 是全域有效,let 只在其所在的代碼塊內生效,出了代碼塊就獲取不到該值,
如下例:(看的可能有點繞,多瞅兩遍)
var 定義的是全域變數,對于 for 回圈來說,整個回圈都只對一個 變數進行操作,看下面例子的第一個回圈,在回圈體內操作 i 會對回圈有影響,由于進行了兩次 i++,所以陣列有部分值為 空,且只進行了部分回圈,
let 定義的是區域變數,對于 for 回圈來說,每次回圈都是不同的作用域,且 let 只對當前作用域有效,更有趣的是,回圈陳述句內部是一個子作用域(即 在內部定義一個同名的 let 變數,不會影響外部的 let 變數),看下面例子的第二個回圈,每次回圈操作,j 都是不同的值,且 回圈內部 定義了 同名的 let 變數 j ,由于作用域的問題,其并不會影響回圈陳述句中的 j,所以執行了全部回圈,
【舉例:】 var a = []; // 用來記錄每次回圈需要列印的初始值 var b = []; // 用來記錄每次回圈的初始值 var count = 0; // 用來記錄回圈的次數 for(var i = 0; i < 10; i++, count++) { a[i] = function() { console.log("當前回圈的值 i 為: " + i); }; b[i] = i++; } console.log("當前回圈執行次數為: " + count); // 由于 i 為全域變數,每次回圈都會進行兩次 i++,所以真實回圈次數小于 10,所以輸出為 5 a[6](); // 由于操作的都是同一變數,所以函式呼叫的是 最后一次修改的 i 值,所以輸出為 10 console.log("每次回圈的初始值 i 為: " + b); // 用于只進行了部分回圈,所有陣列有些并沒有賦值,即為空值,所以輸出為 0,,2,,4,,6,,8 console.log("回圈執行后的 i 值: " + i); // i = 10 時退出回圈, i 為全域變數,所以輸出 為 10 var c = []; // 用來記錄每次回圈需要列印的初始值 var d = []; // 用來記錄每次回圈的初始值 var count = 0; // 用來記錄回圈的次數 for(let j = 0; j < 10; j++, count++) { let j = 5; c[j] = function() { console.log("當前回圈的值 j 為: " + j); }; d[j] = j++; } console.log("當前回圈執行次數為: " + count); // 由于 j 為 區域變數,回圈內部定義的 let 同名變數 j (子作用域)不會影響 回圈陳述句的 j,真實回圈執行 10 次,所以輸出為 10 c[5](); // 每次操作都是不同的變數,且執行了 j++ 操作,所以輸出為 6 console.log("每次回圈的初始值 j 為: " + d); // 由于內部每次都給 d[5] 賦值,其余元素均為空值,所以輸出為 ,,,,,5 console.log("回圈執行后的 j 值: " + j); // 由于 j 為區域變數,只能存在于 for 回圈代碼塊中, 所以此處會報錯,輸出 ReferenceError: j is not defined

(3)特性二:不存在變數提升
變數提升指的是 變數可以在宣告前使用,
let 不存在變數提升,即宣告變數后,才可以使用該變數,不能在宣告前使用,否則會報錯,
【舉例:】 console.log(a); // 不報錯,輸出 undefined console.log(b); // 報錯,輸出 ReferenceError: b is not defined var a = 10; let b = 20;

(4)特性三:暫時性死區
暫時性死區指的是 剛開始進入當前作用域,所要使用的變數就已經存在了,但是不可獲取,當變數被宣告后,才可以獲取該變數,
【舉例:】 var tmp = 123; console.log(tmp); //不報錯,輸出 123 if (true) { console.log(tmp); // 報錯,ReferenceError: Cannot access 'tmp' before initialization let tmp; } 第一次定義 tmp 為 var 型,所以可以正常輸出 123, 進入 if 陳述句后,由于存在 let 定義的 tmp,系統判定 tmp 為區域變數而非全域變數, 導致 console.log(tmp) 中 tmp 出現在 變數宣告前(變數提升失敗), 從而報錯,此處即為暫時性死區,

(5)特性四:不重復宣告
在同一塊 let 作用域中,若使用 let 宣告一個變數,則不能再重復宣告同一個變數,
【舉例:】 // 報錯,Identifier 'a' has already been declared { let a = 1; var a = 2; } // 不報錯,undefined { var a = 1; var a = 2; } // 報錯,Identifier 'a' has already been declared { let a = 1; let a = 2; }
2、const 命令
(1)基本內容
const 通常用來宣告一個只讀的常量,一旦宣告,常量的值不能被修改,且宣告時必須初始化,
用法類似于 let,區域有效、不存在變數提升、不重復宣告,
【舉例:(常量值不可被修改)】 const PI = 3.1415926 console.log(PI); // 輸出 3.1415926 PI = 3.14 // 報錯,輸出 Assignment to constant variable. 【舉例:(常量宣告時需要初始化)】 const a // 報錯,輸出 Missing initializer in const declaration 【舉例:區域有效】 { const PI = 3.1415926; } console.log(PI); // 報錯,輸出 PI is not defined 【舉例:不存在變數提升】 { console.log(PI); // 報錯,輸出 Cannot access 'PI' before initialization const PI = 3.1415926; } 【舉例:不重復宣告】 { var PI = 3.14 const PI = 3.1415926; // 報錯,輸出 SyntaxError: Identifier 'PI' has already been declared }
(2)若 const 宣告的是物件,那么 其不變的是 指向物件的地址,物件的值仍可以改變,可以通過object.freeze() 方法凍結物件(即物件不可修改),
【舉例:var,物件可被修改】 { var f = {name : 'tom', age : '12'}; console.log(f.name + ", " + f.age); // tom, 12 f.name = 'jarry'; f.age = 44; console.log(f.name + ", " + f.age); // jarry, 44 f = {name : 'rick', age : '22'}; console.log(f.name + ", " + f.age); // rick, 22 } 【舉例:const,物件內容可被修改,但是物件不可被修改】 { const f = {name : 'tom', age : '12'}; console.log(f.name + ", " + f.age); // tom, 12 f.name = 'jarry'; f.age = 44; console.log(f.name + ", " + f.age); // jarry, 44 f = {name : 'rick', age : '22'}; // TypeError: Assignment to constant variable. } 【舉例:freeze,物件不可被修改,物件內容不可被修改】 { const f = Object.freeze({name : 'tom', age : '12'}); console.log(f.name + ", " + f.age); // tom, 12 f.name = 'jarry'; f.age = 44; console.log(f.name + ", " + f.age); // tom, 12 f = {name : 'rick', age : '22'}; // TypeError: Assignment to constant variable. }

3、解構運算式
(1)什么是解構?
解構指的是 ES6 支持按照一定的模式,從陣列或者物件中提取值,并將提取的值 對變數進行賦值,
(2)陣列的解構賦值
一般情況下,只要 = 左右兩側 的模式相同,左邊的變數 就會賦值 上 右邊對應的值,
【未使用解構運算式給賦值:】 let a = 10; let b = 20; let c = 30; console.log(a, b, c); 【使用 解構運算式賦值:】 let [a, b, c] = [100, 200, 300]; console.log(a, b, c);

解構不成功時,對應的資料為 undefined,
允許解構賦值指定默認值,默認值可以為一個函式(惰性,用到時才呼叫),
【嵌套陣列賦值:】 let [a, [b, [c, d]]] = [1, [2, [3, 4]]]; console.log(a, b, c, d); // 輸出 1 2 3 4 let [head, ...tail] = [1, 2, 3, 4]; console.log(head); // 輸出 1 console.log(tail); // 輸出 (3) [2, 3, 4] let [x, y, ...z] = [1]; console.log(x); // 輸出 1 console.log(y); // 輸出 undefined console.log(z); // 輸出 [] 【部分解構:(給匹配上的變數賦值)】 let [x, y, z] = [1, 2]; console.log(x); // 輸出 1 console.log(y); // 輸出 2 console.log(z); // 輸出 undefined let [a, [b], c] = [1, [2, 3], 4]; console.log(a); // 輸出 1 console.log(b); // 輸出 2 console.log(c); // 輸出 4 【解構時使用默認值:(即若賦值失敗,可以使用默認值)】 function hello() { return "hello"; } let [x=hello(), y=hello(), z=100] = [1, 2, 3]; console.log(x); // 輸出 1 console.log(y); // 輸出 2 console.log(z); // 輸出 3 let [x2=hello(), y2=hello(), z2=100] = [, 2, ]; console.log(x2); // 輸出 hello console.log(y2); // 輸出 2 console.log(z2); // 輸出 100
(3)物件的解構賦值
物件同樣可以進行解構,與陣列解構不同的是,物件解構時根據屬性名進行匹配,不需要注意順序,
屬性名不匹配時,值為 undefined,
可以自定義屬性名,使用 : 去指定,
如下例:
let {name, age} 等價于 let {name: name, age: age}
【根據屬性名匹配:】 let {name, age} = {name: "tom", age: 22}; console.log(name); // 輸出 tom console.log(age); // 輸出 22 【屬性名匹配不成功,回傳 undefined:】 let {name2, age2} = {name: "tom", age: 22}; console.log(name2); // 輸出 undefined console.log(age2); // 輸出 undefined 【自定義屬性名匹配:】 let {name: name3, age: age3} = {name: "tom", age: 22}; console.log(name3); // 輸出 tom console.log(age3); // 輸出 22

4、字串拓展
即加強了字串處理功能,
(1)字符的 unicode 表示
JavaScript 允許使用使用 \uxxxx 的形式表示一個字符,其中 xxxx 表示 unicode 值,但是這種寫法只支持 \u0000 ~ \uffff,超出這個限制需要使用 雙位元組 進行表示,
比如:
\u1F680 會決議成 \u1F68 和 0,若想正常顯示,需使用雙位元組 \uD83D\uDE80 表示,
【舉例:】 console.log("\u0061"); // 輸出 a console.log("\u00614"); // 輸出 a4

ES6 可以使用 大括號將 xxxxx 括起來,從而正確解讀,
【舉例:】 console.log("\u{0061}"); console.log("\u{1F680}"); console.log("\uD83D\uDE80");

(2)新增方法 -- includes()、startsWith()、endsWith()
JavaScript 中通過 indexOf() 可以確定某個字符串中是否包含另外一個字串,
ES6 新增三個方法用于判斷字串中是否包含另一個字串,
includes() 回傳布林值,true 表示當前字串中存在另一個字串,false 表示不存在,
startsWith() 回傳布林值,true 表示當前字串的頭部存在另一個字串,false 表示不存在,
endsWith() 回傳布林值,true 表示當前字串的尾部存在另一個字串,false 表示不存在,
【舉例:】 let test = "hello world"; console.log(test.includes("wo")); // 輸出 true console.log(test.startsWith("he")); // 輸出 true console.log(test.endsWith("ld")); // 輸出 true console.log(test.includes("helloworld")); // 輸出 false

(3)模板字串(``)
模板字串是增強版的字串,使用 反引號(``) 標識字串,可以作為普通字串使用,可以定義多行字串,內部使用 ${} 可以嵌入變數、函式、運算式等并決議,
【舉例:】 let [name, age] = ["tom", 32]; function fun() { return "helloworld"; } let test2 = `${name}, age = ${age - 10}, say ${fun()}`; console.log(test2);

5、物件的拓展
拓展物件的用法,
(1)屬性簡寫
ES6 允許在 物件中 直接寫變數,此時 屬性為 變數名,屬性值為 變數值,即 {a} 等價于 {a: a}
【舉例:】 let a = "hello"; let b = {a}; console.log(b); // 輸出 {a: "hello"} let c = {a: a}; console.log(c); // 輸出 {a: "hello"} let d = {g: "hello"}; console.log(d); // 輸出 {g: "hello"}

物件中的方法也可以簡寫,
【舉例:】 let [name, age] = ["tom", 32]; let person = { name, age, hello() { console.log(`${name}, ${age}`); }, hello2: function() { console.log(`${name}, ${age}`); } }; person.hello(); person.hello2();

(2)新增方法 -- assign()
Object.assign() 方法用于物件的合并,
其實作的是淺拷貝,即若 源物件中的某個屬性值 仍是一個物件,那么目標物件 中拷貝得到的是這個物件的參考,即對源物件中這個物件進行修改,會影響到目標物件,
【格式:】 Object.assign(target, source1, ...source2); 注: target 為目標物件,source1, ...source2 等都是源物件, 該方法是將 源物件 的值 復制 到 目標物件 中, 若出現同名屬性,則后者會覆寫前者, 即 target、source1、source2 中存在同名屬性,則最后 target 的那個同名屬性為 source2 的屬性, 【舉例:】 let tom = { name: "tom", age: 32, teacher: { chinese: "rose", english: "jack" } }; let jarry = { name: "jarry", age: 33, email: "[email protected]" }; let people = Object.assign({}, tom, jarry); console.log(people); tom.teacher.chinese = "rick"; console.log(people);

如何實作深拷貝嘞:
有一種解決辦法:(具體原因沒有仔細深究)
先將物件轉為 json 字串,再將 字串轉為物件,
將上例 let people = Object.assign({}, tom, jarry); 改為 let people = Object.assign({}, JSON.parse(JSON.stringify(tom)), jarry);

(3)新增物件遍歷方法 -- keys()、values()、entries()
Object.keys() 獲取物件 key 形成的陣列,
Object.values() 獲取物件 value 形成的陣列,
Object.entries() 獲取物件 key - value 形成的 二維陣列,
【舉例:】 let people = { name: "tom", age: 22 }; console.log(Object.keys(people)); console.log(Object.values(people)); console.log(Object.entries(people));

(4)擴展運算子(...)
用于取出物件、陣列的引數并拷貝到當前物件中,
若資料重復,會覆寫,等同于 Object.assign(),
【舉例:】 let people = { name: "tom", age: 22 }; let people2 = { name: "jarry", age: 33 }; console.log({people, people2}); console.log({...people, ...people2}); let a = [3, 1, 2]; console.log(a); console.log(...a);

6、函式的拓展
(1)函式引數默認值
可以在定義函式的同時,指定函式的默認值,呼叫時,若未傳遞引數,則使用默認值,
【舉例:】 function test (x, y) { y = y || "hello"; console.log(x + "======" + y); } test("tom"); // 輸出 tom======hello test("tom", "helloworld"); // 輸出 tom======helloworld function test2 (x, y = "hello") { console.log(x + "======" + y); } test2("tom"); // 輸出 tom======hello test2("tom", "helloworld"); // 輸出 tom======helloworld

(2)rest 引數
rest 引數 ,形式為 ...變數名, 用于接收多個引數,保存在陣列中,
若有多個引數,則 rest 必須放在最后,否則會報錯,
【舉例:】 function test (...values) { // for of 每次獲取的是陣列的值 for (let j of values) { console.log(j); } } test(8, 7, 9); function test2 (...values) { // for in 每次獲取的是陣列的下標 for (let j in values) { console.log(values[j]); } } test2(8, 7, 9); function test3 (...values, y) { // 報錯,SyntaxError: Rest parameter must be last formal parameter for (let j in values) { console.log(values[j]); } }

(3)箭頭函式
ES6 支持 使用 箭頭 => 定義函式,
【使用箭頭函式定義 函式:】 var f = v => v; console.log(f(3)); // 3 // 等價于 var f = function(v){ return v; } console.log(f(3)); // 3

如果沒有引數、或者有多個引數,需使用圓括號 () 代替引數部分,
如果方法體(代碼塊)只有一條陳述句,則 return 可以省略,
【使用 () 代替引數:】 var f = () => 5; // 等價于 var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2; // 等價于 var sum = function(num1, num2) { return num1 + num2; };
如果方法體(代碼塊)存在多條陳述句,則需要使用大括號 {} 括起來,并使用 return 回傳值,
【舉例:】 var fun = () => { let num = 7; let num2 = num + 3; return num + num2; }; console.log(fun()); // 17 // 等價于 var fun = function() { let num = 7; let num2 = num + 3; return num + num2; }; console.log(fun()); // 17

若回傳的是一個物件,則必須在物件外面加上圓括號 (),否則 {} 會被當成代碼塊被決議,
【舉例:】 var getPeopleItem = id => ({ id: id, name: "Temp" }); console.log(getPeopleItem(3)); // {id: 3, name: "Temp"} var getPeopleItem = id => { id: id, name: "Temp" }; console.log(getPeopleItem(3)); // SyntaxError: Unexpected token :

解構與箭頭函式可以一起使用:
【舉例:】 let people = { name: "tom", age: 22 }; let fun = (param) => { console.log(param.name + "==========" + param.age); }; fun(people); let fun2 = ({name, age}) => { console.log(name + "==========" + age); }; fun2(people);

7、陣列常用方法
參考:https://www.cnblogs.com/l-y-h/p/12150578.html
(1)新增方法 -- reduce()
Array.reduce(callback[, initialValue]) 用于給陣列的每一個元素執行一個回呼函式,
其中 :
initialValue 為第一次執行 callback 時的引數值,可以省略,
callback 有四個引數,callback(previousValue, currentValue, index, array).
previousValue 指上一次執行回呼的函式值,或者初始值,
currentValue 指陣列當前被處理的元素
index 指當前陣列元素的下標
array 指當前的陣列
【舉例:】 let arr = [4, 6, 5]; let newArr = arr.reduce((previousValue, currentValue, index, array) => { console.log("上一次處理的值為: " + previousValue); console.log("當前處理的值為: " + currentValue); console.log("當前元素下標為: " + index); console.log("當前陣列元素為: " + array[index]); return currentValue * 2; }); console.log(newArr);

8、Promise 物件
(1)什么是 Promise ?
Promise 是一個異步編程的一種解決方案,可以理解為一個容器,里面保存著未來才會結束的某個操作(異步操作)的結果,通過 Promise 物件可以獲取異步操作的訊息,
(2)Promise 特點
特點一:物件的狀態不受外界影響,
Promise 有三種狀態,Pending (進行中)、Resolved (解決)、Rejected (失敗),只有異步操作的結果能決定 Promise 處于哪種狀態,其余操作無法改變該狀態,無法中途取消操作,
特點二:狀態改變后,不再變化,
狀態改變的情況,Pending -> Resolved 、 Pending -> Rejected,
一旦狀態改變,其不會再改變,
(3)Promise 缺點
無法取消Promise,一旦新建便會執行,無法中途取消,
如果不設定回呼函式,Promise內部的錯誤不會向外拋出,
處于Pending時,無法判斷該操作是剛開始還是即將完成,
(4)如何使用?
需要使用 new 去實體化一個 Promise 物件,引數為 一個函式,
函式的引數為 resolve、reject ,引數為兩個函式,由 JavaScript 引擎提供,
resolve 函式是改變狀態, Pending -> Resolved ,即異步操作成功后呼叫,并將異步操作的成功結果作為引數向外傳遞,
reject 函式也是改變狀態, Pending -> Rejected,即異步操作失敗后呼叫,并將異步操作的失敗結果作為引數向外傳遞,
使用 then 方法可以處理 resolve、reject 傳遞出來的結果,其接受兩個回呼函式作為引數,第一個回呼函式用來處理 resolve 傳遞的結果,第二個回呼函式用來處理 reject 傳遞的結果,第二個回呼函式可選,
一般情況下,使用 catch 方法處理 reject 傳遞出來的結果,其作用等價于 then 方法中的第二個回呼函式,
【格式:】 var promise = new Promise((resolve, reject) => { if(異步操作成功) { resolve(data); } else { reject(error); } }); promise.then((data) => { // 成功的操作 }).catch((error) => { // 失敗的操作 });
9、模塊化
(1)什么是模塊化?
模塊化就是把代碼進行拆分,方便重復利用,類似于 Java 中的各種 jar 包,
模塊化兩個主要命令:export、import,
export:用于規定模塊的對外介面,即通過 export 可以獲取模塊的內容,
import:用于匯入模塊,即通過 import 可以與其他模塊建立起聯系,
(2)export 命令
通常一個模塊就是一個檔案,該檔案內部的變數、陣列、物件 等外界都不能獲取,需要使用 export 將其匯出,
export 可以匯出 基本型別變數、函式、陣列、物件等,
【匯出方式一:】 export var test = "hello"; 【匯出方式二:】 var a = "hello"; var b = [1, 2, 3]; export {a, b}; 匯出方式一、匯出方式二 對外暴露的介面名 為 變數名、函式名等, 使用 import 要填寫正確的介面名,才能正常參考模塊,否則會出錯, 【匯出方式三:(使用 as 自定義介面名)】 var a = "hello"; var b = [1, 2, 3]; export { a as AA, b as BB }; 【匯出方式四:(使用 default 可以忽略介面名,此時 import 可以自定義介面名)】 export default { var a = "hello"; var b = [1, 2, 3]; }
(3)import 命令
export 定義了模塊對外的介面后,可以使用 import 匯入相應的模塊功能,
【匯入方式一:(使用 {} 可以一次接受多個模塊介面名)】 import {a, b} from 'xx/xx.js'; 【匯入方式二:(使用 as 取名)】 import {a as AA, b as BB} from 'xx/xx.js'; 【匯入方式三:(對于 export default 的模塊,可以任意取名)】 import test from 'xx/xx.js';
未完待續...
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/117335.html
標籤:JavaScript
