技術(shù)交流QQ群:1027579432,歡迎你的加入!
歡迎關(guān)注我的微信公眾號(hào):CurryCoder的程序人生
1.什么是ES6
- ES的全稱是ECMAScript,它是由ECMA國(guó)際標(biāo)準(zhǔn)化組織制定的一項(xiàng)腳本語言的標(biāo)準(zhǔn)化規(guī)范。ES6實(shí)際上是一個(gè)泛指,泛指ES2015及之后的版本。
ECMA版本迭代.png
2.為什么使用ES6?
- 每一次標(biāo)準(zhǔn)的誕生都意味著語言的完整,功能的加強(qiáng)。JavaScript語言本身也有一些令人不滿意的地方:
- 變量提升特性增加了程序運(yùn)行時(shí)的不可預(yù)測(cè)性。
- 語法過于松散,實(shí)現(xiàn)相同的功能,不同的人可能會(huì)寫出不同的代碼。
3.ES6新增語法之let
-
ES6中新增的用于聲明變量的關(guān)鍵字。使用let聲明的變量具有以下特點(diǎn):
- (1).let聲明的變量具有塊級(jí)作用域(只在所處的塊級(jí)有效);注意:使用let關(guān)鍵字聲明的變量才具有塊級(jí)作用域,使用var聲明的變量不具有塊級(jí)作用域特性。
/* if(true) { // let關(guān)鍵字聲明的變量具有塊級(jí)作用域{} let a = 10; let b = 20; console.log(b); if (true) { let c = 30; } console.log(c); // c is not defined } console.log(a); // a is not defined console.log(b); // b is not defined */ console.log('-------------------------'); // 在一個(gè)大括號(hào){}中,使用let關(guān)鍵字聲明的變量才具有塊級(jí)作用域,var關(guān)鍵字聲明的變量不具有塊級(jí)作用域 if (true) { let num = 100; var abc = 10000; } console.log(abc); // 10000 // console.log(num); // num is not defined console.log('-------------------------'); // let關(guān)鍵字聲明的變量具有塊級(jí)作用域{},防止循環(huán)變量變成全局變量 for (var i = 0; i < 2; i++) { } console.log(i); // 2 for (let i = 0; i < 2; i++) { } console.log(i); // i is not defined- (2).使用let關(guān)鍵字聲明的變量不存在變量提升(必須先聲明再使用)。
// 使用let關(guān)鍵字聲明的變量不存在變量提升(必須先聲明再使用) console.log(aaa); // undefined var aaa = 34; console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization let a = 20;- (3).使用let關(guān)鍵字聲明的變量具有暫時(shí)性死區(qū)特性
// let關(guān)鍵字聲明的變量具有暫時(shí)性死區(qū)特性 // /* var tmp = 123; // if(true){ // tmp = 'abc'; // 暫時(shí)性死區(qū)特性:此處的tmp并不等于全局變量tmp=123。因此,會(huì)報(bào)錯(cuò)Uncaught ReferenceError: Cannot access 'tmp' before initialization // let tmp; // } */ var num = 10; if (true) { console.log(num); // Uncaught ReferenceError: Cannot access 'num' before initialization let num = 20; } -
關(guān)于let關(guān)鍵字的經(jīng)典面試題
var arr = []; for(var i = 0; i < 2; i++){ arr[i] = function() { console.log(i); } } arr[0](); arr[1]();-
上題中的關(guān)鍵點(diǎn)在于:變量i是全局的,函數(shù)執(zhí)行時(shí)輸出的都是全局作用域下的i值。
熱身題.png
// 進(jìn)階題 var arr = []; for(let i = 0; i < 2; i++){ arr[i] = function() { console.log(i); } } arr[0](); // 0 arr[1](); // 1-
上題中的關(guān)鍵點(diǎn)在于:每次循環(huán)都會(huì)產(chǎn)生一個(gè)塊級(jí)作用域,每個(gè)塊級(jí)作用域中的變量都是不同的,函數(shù)執(zhí)行時(shí)輸出的是自己上一級(jí)作用域(循環(huán)產(chǎn)生的塊級(jí)作用域)下的i值。
進(jìn)階題.png
-
上題中的關(guān)鍵點(diǎn)在于:變量i是全局的,函數(shù)執(zhí)行時(shí)輸出的都是全局作用域下的i值。
4.ES6新增語法之const
- const作用:聲明常量,常量就是值(內(nèi)存地址)不能變化的量。
- 使用const聲明的常量具有以下特點(diǎn):
- (1).具有塊級(jí)作用域
// 使用const聲明的常量,具有塊級(jí)作用域 if(true){ const a = 10; if(true){ const a = 200; console.log(a); // 200 } console.log(a); // 10 } console.log(a); // a is not defined- (2).聲明常量時(shí)必須賦初始值
// 使用const關(guān)鍵字聲明的常量必須賦初始值 // const PI; // Missing initializer in const declaration const PI = 65;- (3).常量賦值以后,值不能修改
- 基本數(shù)據(jù)類型:值就不可以被更改;
- 復(fù)雜數(shù)據(jù)類型(如數(shù)組、對(duì)象):復(fù)雜數(shù)據(jù)類型常量?jī)?nèi)部的值可以被更改,復(fù)雜數(shù)據(jù)類型常量本身不能被更改。
// 使用const關(guān)鍵字聲明常量賦值后,值不能修改。 const PI = 3.14; // PI = 122; Assignment to constant variable. const arr = [100, 200]; arr[0] = 'a'; arr[1] = 'b'; console.log(arr); // ['a', 'b'] // arr = ['a', 'b']; Assignment to constant variable.
5.let、const、var三者的對(duì)比
- 使用var聲明的變量,其作用域?yàn)樵撜Z句所在的函數(shù)內(nèi),且存在變量提升現(xiàn)象。
- 使用let聲明的變量,其作用域?yàn)樵撜Z句所在的代碼塊內(nèi),不存在變量提升。
- 使用const聲明的是常量,在后面出現(xiàn)的代碼中不能再修改該常量的值。
三者的對(duì)比.png
6.ES6新增語法之解構(gòu)賦值
- 解構(gòu)賦值:按照一定模式,從數(shù)組或?qū)ο笾刑崛≈担瑢⑻崛〕鰜淼闹蒂x給另外的變量。
6.1 數(shù)組解構(gòu)
- 數(shù)組解構(gòu):允許我們按照一一對(duì)應(yīng)的關(guān)系從數(shù)組中提取值,然后將值賦值給變量。
let [a, b, c] = [1, 10, 100]; console.log(a); // 1 console.log(b); // 10 console.log(c); // 100 -
如果解構(gòu)不成功,變量的值為undefined。
// 如果解構(gòu)不成功,變量的值為undefined let arr1 = [1, 11, 111]; let [aa, bb, cc, dd, ee] = arr1; console.log(aa); // 1 console.log(bb); // 11 console.log(cc); // 1111 console.log(dd); // undefined console.log(ee); // undefined
6.2 對(duì)象解構(gòu)
- 對(duì)象解構(gòu):允許我們使用變量的名字匹配對(duì)象的屬性,匹配成功將對(duì)象屬性的值賦值給變量。
// 對(duì)象解構(gòu):允許我們使用變量的名字匹配對(duì)象的屬性,匹配成功將對(duì)象屬性的值賦值給變量 let person = { name: 'CurryCoder', age: 18, sex: 'male' }; let {name, age, sex, address} = person; // 對(duì)象解構(gòu),大括號(hào)中的變量名必須與person對(duì)象中的屬性名相同!!!! console.log(name); // 'CurryCoder' console.log(age); // 18 console.log(sex); // 'male' console.log(address); // undefined -
對(duì)象解構(gòu)的另一種形式:上面的這種對(duì)象解構(gòu)形式,要求必須對(duì)象解構(gòu)中變量的名字一定要和對(duì)象的屬性名相同。這樣的寫法限制性太強(qiáng),因此可以給對(duì)象的屬性名起個(gè)別名。
// 對(duì)象解構(gòu)的另一種形式 let {name: myName, age: myAge} = person; // myName myAge屬于別名,是真正的變量 console.log(myName); // 'CurryCoder' console.log(myAge); // 18
7.箭頭函數(shù)
-
ES6中新增的定義函數(shù)的方式,用來簡(jiǎn)化ES6之前函數(shù)定義語法的。語法格式如下:
() => {} -
由于箭頭函數(shù)沒有函數(shù)名,因此將箭頭函數(shù)賦值給一個(gè)變量,變量名即函數(shù)名。通過變量名調(diào)用箭頭函數(shù)就可以了。
// 箭頭函數(shù): 用來簡(jiǎn)化函數(shù)定義語法的 const fn = () => { console.log(123); } // 調(diào)用箭頭函數(shù) fn(); -
箭頭函數(shù)的特點(diǎn):
- (1).當(dāng)函數(shù)體中只有一句代碼,且代碼的執(zhí)行結(jié)果就是返回值。此時(shí),可以省略箭頭函數(shù)中的大括號(hào){}。
// 箭頭函數(shù)特點(diǎn)1:當(dāng)函數(shù)體中只有一句代碼,且代碼的執(zhí)行結(jié)果就是返回值。此時(shí),可以省略大括號(hào) const fun = (num1, num2) => num1 + num2; console.log(fun(11, 100));- (2).如果箭頭函數(shù)的形參只有一個(gè),可以省略小括號(hào)()。
// 箭頭函數(shù)特點(diǎn)2:如果箭頭函數(shù)的形參只有一個(gè),可以省略小括號(hào)() const f1 = n => { console.log('只有一個(gè)形參的箭頭函數(shù)'); console.log(n); } f1(666); -
箭頭函數(shù)中的this指向問題:箭頭函數(shù)不綁定this關(guān)鍵字,箭頭函數(shù)中的this,指向的是箭頭函數(shù)定義位置的上下文的this。
// 箭頭函數(shù)中的this指向問題**:箭頭函數(shù)不綁定this關(guān)鍵字,箭頭函數(shù)沒有自己的this關(guān)鍵字,如果在箭頭函數(shù)中使用this,this將指向箭頭函數(shù)定義位置中的this const obj = { name: "CurryCoder", age: 18 }; function fn(){ console.log(this); // obj return () => { console.log(this); // obj } } const resFn = fn.call(obj); resFn(); -
箭頭函數(shù)面試題
// var age = 100; // window對(duì)象的age屬性 var obj = { age: 18, say: () => { alert(this.age); // undefined,this實(shí)際上執(zhí)向的是window對(duì)象 } } obj.say();
8.剩余參數(shù)...args
-
剩余參數(shù)允許我們將一個(gè)不定數(shù)量的參數(shù)表示為一個(gè)數(shù)組。
// 剩余參數(shù) const fn = (first, ...args) => { console.log(first); // 10 console.log(args); // [20, 30] }; fn(10, 20, 30); // 在箭頭函數(shù)中無法使用數(shù)組的arguments傳遞不定數(shù)量的參數(shù) const sum = (...args) => { let total = 0; args.forEach(item => total += item); return total; }; console.log(sum(1, 11)); console.log(sum(1, 11, 111)); -
剩余參數(shù)和解構(gòu)配合使用
let arr = ['Curry', 'Harden', 'James']; let [s1, ...s2] = arr; // 數(shù)組解構(gòu) + 剩余參數(shù) console.log(s1); // 'Curry' console.log(s2); // ['Harden', 'James']
9.ES6的內(nèi)置對(duì)象擴(kuò)展
9.1 數(shù)組Array的擴(kuò)展方法
- 擴(kuò)展運(yùn)算符可以將數(shù)組或?qū)ο筠D(zhuǎn)換為用逗號(hào)分隔的參數(shù)序列。
-
數(shù)組的擴(kuò)展運(yùn)算符:擴(kuò)展運(yùn)算符可以將數(shù)組拆分成以逗號(hào)分隔的參數(shù)序列
// 數(shù)組的擴(kuò)展運(yùn)算符 let arr = [1, 2, 3]; // ...ary 擴(kuò)展運(yùn)算符可以將數(shù)組拆分成以逗號(hào)分隔的參數(shù)序列即 1, 2, 3 // 以下兩句是等價(jià)的 console.log(...arr); // 1 2 3 console.log(1, 2, 3); // 1 2 3 -
擴(kuò)展運(yùn)算符可以應(yīng)用于合并數(shù)組。
// 方法1 let arr1 = [1, 2, 3]; let arr2 = ['a', 'b', 'c']; // ...arr1即1, 2, 3 // ...arr2即'a', 'b', 'c' let arr3 = [...arr1, ...arr2]; console.log(arr3); // [1, 2, 3, 'a', 'b', 'c'] // 方法2 arr1.push(...arr2); console.log(arr1); // [1, 2, 3, 'a', 'b', 'c'] -
利用擴(kuò)展運(yùn)算符將偽數(shù)組或可遍歷對(duì)象轉(zhuǎn)換為真正的數(shù)組。
let div = document.querySelectorAll('div'); console.log(div); // 偽數(shù)組 console.log(typeof div); // 類型為對(duì)象 div = [...div]; // 真正的數(shù)組 console.log(div); div.push('a'); console.log(div); -
構(gòu)造函數(shù)方法Array.from():將偽數(shù)組或可遍歷對(duì)象轉(zhuǎn)換為真正的數(shù)組。
let arr = { // arr是偽數(shù)組 '0': 'one', '1': 'two', '2': 'three', 'length': 3 }; let arr1 = Array.from(arr); // arr1是真正的數(shù)組 console.log(arr1); - Array.from()方法還可以接收第二個(gè)參數(shù)(是一個(gè)函數(shù)),作用類似于數(shù)組的map方法,用來對(duì)每個(gè)元素進(jìn)行處理,將處理后的值放入返回的數(shù)組。
let arr = { // arr是偽數(shù)組 '0': 'one', '1': 'two', '2': 'three', 'length': 3 }; let arr1 = Array.from(arr); // arr1是真正的數(shù)組 console.log(arr1); // ["one", "two", "three"] // Array.from()方法還可以接收第二個(gè)參數(shù)(是一個(gè)函數(shù)),作用類似于數(shù)組的map方法,用來對(duì)每個(gè)元素進(jìn)行處理,將處理后的值放入返回的數(shù)組。 let oldArr = { '0': '0', '1': '1', '2': '2', 'length': 3 } let newArr = Array.from(oldArr, item => item * 2); console.log(newArr); // [0, 2, 4] -
實(shí)例方法find():用于找出第一個(gè)符合條件的數(shù)組成員,如果沒有找到就返回undefined
let oldArr = [{ id: 1, name: "CurryCoder" }, { id: 2, name: "Durant" }]; let target = oldArr.find((item, index) => item.id == 2); console.log(target); // id==3不存在,返回undefined // 結(jié)果如下所示: /* { id: 2, name: "Durant" } */ -
實(shí)例方法findeIndex():用于找出第一個(gè)符合條件的數(shù)組成員的位置,如果沒有找到返回-1。
// 實(shí)例方法findeIndex():用于找出第一個(gè)符合條件的數(shù)組成員的位置,如果沒有找到返回-1 let arr = [1, 5, 30, 96]; let index = arr.findIndex((value, index) => value > 5); console.log(index); // 2 let index1 = arr.findIndex((value, index) => value > 555); console.log(index1); // -1 -
實(shí)例方法includes():表示某個(gè)數(shù)組是否包含給定的值,返回布爾值。
// 實(shí)例方法includes():表示某個(gè)數(shù)組是否包含給定的值,返回布爾值。 let arr = [1, 2, 666]; console.log(arr.includes(666)); // true console.log(arr.includes(888)); // false
9.2 字符串string的擴(kuò)展方法
-
模板字符串:ES6新增的創(chuàng)建字符串的方式,使用反引號(hào)`定義。
let name = `CurryCoder`; // 模板字符串用``包裹 console.log(name); - 模板字符串的特點(diǎn):
- (1).模板字符串中可以解析變量
let name = `CurryCoder`; // 模板字符串用``包裹 // 模板字符串中可以解析變量,不需要字符串拼接操作 let sayHi = `Hi, my name is ${name}`; console.log(sayHi); // Hi, my name is CurryCoder- (2).模板字符串中也可以換行
// 模板字符串中也可以換行 let result = { name: 'CurryCoder', age: 18, sex: 'male' } let html = ` <div> <span>${result.name}</span> <span>${result.age}</span> <span>${result.sex}</span> </div>`;- (3).模板字符串中也可以調(diào)用函數(shù)
// 模板字符串中也可以調(diào)用函數(shù) const sayHello = () => { return 'Hello World!'; }; let greet = `${sayHello()} 模板字符串中可以調(diào)用函數(shù)sayHello啦~`; console.log(greet); -
實(shí)例方法startsWith()和endsWith()
- startsWith():表示參數(shù)字符串是否在原字符串的頭部,返回布爾值。
- endsWith():表示參數(shù)字符串是否在原字符串的尾部,返回布爾值。
let src = 'Hello World~'; // startsWith():表示參數(shù)字符串是否在原字符串的頭部,返回布爾值。 let res = src.startsWith('Hello'); console.log(res); // true // endsWith():表示參數(shù)字符串是否在原字符串的尾部,返回布爾值。 let result = src.endsWith('~'); console.log(result); // true -
實(shí)例方法repeat():repeat()方法表示將原字符串重復(fù)n次,返回一個(gè)新的字符串。
// 實(shí)例方法repeat():repeat()方法表示將原字符串重復(fù)n次,返回一個(gè)新的字符串 let src = 'Curry|'; let target = src.repeat(3); console.log(target); // Curry|Curry|Curry| console.log(src === target); // false
9.3 Set數(shù)據(jù)結(jié)構(gòu)
- ES6提供了新的數(shù)據(jù)結(jié)構(gòu)Set。它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。
- Set本身是一個(gè)構(gòu)造函數(shù),用來生成Set數(shù)據(jù)結(jié)構(gòu)。
const s = new Set(); console.log(s.size); // 0 - Set函數(shù)可以接收一個(gè)數(shù)組作為參數(shù),用來初始化。
// 數(shù)組去重 const set = new Set([1, 2, 3, 4, 4, 4, 5, 6]); console.log(set.size); // 6 const arr = [...set]; console.log(arr); // [1, 2, 3, 4, 5, 6] -
Set數(shù)據(jù)結(jié)構(gòu)實(shí)例方法
- add(value):添加某個(gè)值,返回Set結(jié)構(gòu)本身
- delete(value):刪除某個(gè)值,返回一個(gè)布爾值,表示刪除是否成功
- has(value):返回一個(gè)布爾值,表示該值是否為Set的成員
- clear():清除所有成員,沒有返回值
const s = new Set(); s.add(1).add(2).add(3); // 向set結(jié)構(gòu)中添加值 console.log(s.size); const result = s.delete(2); // 刪除set結(jié)構(gòu)中的2 console.log(result); // true console.log(s.size); const res = s.has(1); // set結(jié)構(gòu)中是否有1這個(gè)值,返回布爾值 console.log(res); s.clear(); // 清除set結(jié)構(gòu)中的所有值 console.log(s.size); -
遍歷:Set數(shù)據(jù)結(jié)構(gòu)的實(shí)例與數(shù)組一樣,也擁有forEach()方法,用于對(duì)每個(gè)成員執(zhí)行某種操作,沒有返回值。
// Set數(shù)據(jù)結(jié)構(gòu)的實(shí)例與數(shù)組一樣,也擁有forEach()方法,用于對(duì)每個(gè)成員執(zhí)行某種操作,沒有返回值 const s = new Set(['a', 'b', 'c']); s.forEach(value => console.log(value));



