es6經常使用的語法,和不得不知的es6小技巧


1. 強制要求參數

ES6提供了默認參數值機制,容許你爲參數設置默認值,防止在函數被調用時沒有傳入這些參數。
在下面的例子中,咱們寫了一個required()函數做爲參數a和b的默認值。這意味着若是a或b其中有一個參數沒有在調用時傳值,會默認required()函數,而後拋出錯誤。javascript

`const required = () => {``throw` `new` `Error(``'Missing parameter'``)};`
`const add = (a = required(), b = required()) => a + b;`
`add(1, 2)` `//3`
`add(1)` `// Error: Missing parameter.`
複製代碼

2. 強大的reduce

數組的reduce方法用途很廣。它通常被用來把數組中每一項規約到單個值。可是你能夠利用它作更多的事。php

2.1 使用reduce同時實現map和filter

假設如今有一個數列,你但願更新它的每一項(map的功能)而後篩選出一部分(filter的功能)。若是是先使用map而後filter的話,你須要遍歷這個數組兩次。
在下面的代碼中,咱們將數列中的值翻倍,而後挑選出那些大於50的數。有注意到咱們是如何很是高效地使用reduce來同時完成map和filter方法的嗎?前端

`const numbers = [10, 20, 30, 40];`
`const doubledOver50 = numbers.reduce((finalList, num) => {`
`num = num * 2; `
`if` `(num > 50) {`
`finalList.push(num);`
`}`
`return` `finalList;`
`}, []);`
`doubledOver50;` `// [60, 80]`
歡迎加入全棧開發交流划水交流圈:582735936
面向划水1-3年前端人員
幫助突破划水瓶頸,提高思惟能力
複製代碼

2.2 使用reduce取代map和filter

若是你認真閱讀了上面的代碼,你應該能理解reduce是能夠取代map和filter的。java

2.3 使用reduce匹配圓括號

reduce的另一個用途是可以匹配給定字符串中的圓括號。對於一個含有圓括號的字符串,咱們須要知道(和)的數量是否一致,而且(是否出如今)以前。
下面的代碼中咱們使用reduce能夠輕鬆地解決這個問題。咱們只須要先聲明一個counter變量,初值爲0。在遇到(時counter加一,遇到)時counter減一。若是左右括號數目匹配,那最終結果爲0。面試

`//Returns 0 if balanced.`
`const isParensBalanced = (str) => {`
`return` `str.split(``''``).reduce((counter, char) => {`
`if``(counter < 0) {` `//matched ")" before "("`
`return` `counter;`
`}` `else` `if``(char ===` `'('``) {`
`return` `++counter;`
`}` `else` `if``(char ===` `')'``) {`
`return` `--counter;`
`}` `else` `{` `//matched some other char`
`return` `counter;`
`}`
`}, 0);` `//<-- starting value of the counter}`
`isParensBalanced(``'(())'``)` `// 0 <-- balanced`
`isParensBalanced(``'(asdfds)'``)` `//0 <-- balanced`
`isParensBalanced(``'(()'``)` `// 1 <-- not balanced`
`isParensBalanced(``')('``)` `// -1 <-- not balanced`
歡迎加入全棧開發交流划水交流圈:582735936
面向划水1-3年前端人員
幫助突破划水瓶頸,提高思惟能力

複製代碼

2.4 統計數組中相同項的個數

不少時候,你但願統計數組中重複出現項的個數而後用一個對象表示。那麼你可使用reduce方法處理這個數組。
下面的代碼將統計每一種車的數目而後把總數用一個對象表示。編程

`var` `cars = [``'BMW'``,``'Benz'``,` `'Benz'``,` `'Tesla'``,` `'BMW'``,` `'Toyota'``];`
`var` `carsObj = cars.reduce(``function` `(obj, name) {`
`obj[name] = obj[name] ? ++obj[name] : 1;`
`return` `obj;`
`}, {});`
`carsObj;` `// => { BMW: 2, Benz: 2, Tesla: 1, Toyota: 1 }`
複製代碼

reduce的其餘用處實在是太多了,建議閱讀MDN的相關代碼示例。數組

3. 對象解構

3.1 刪除不須要的屬性

有時候你不但願保留某些對象屬性,也許是由於它們包含敏感信息或僅僅是太大了(just too big)。你可能會枚舉整個對象而後刪除它們,但實際上只須要簡單的將這些無用屬性賦值給變量,而後把想要保留的有用部分做爲剩餘參數就能夠了。
下面的代碼裏,咱們但願刪除_internal和tooBig參數。咱們能夠把它們賦值給internal和tooBig變量,而後在cleanObject中存儲剩下的屬性以備後用。ruby

`let {_internal, tooBig, ...cleanObject} = {el1:` `'1'``, _internal:``"secret"``, tooBig:{}, el2:` `'2'``, el3:` `'3'``};`
`console.log(cleanObject);` `// {el1: '1', el2: '2', el3: '3'}`
複製代碼

3.2 在函數參數中解構嵌套對象

在下面的代碼中,engine是對象car中嵌套的一個對象。若是咱們對engine的vin屬性感興趣,使用解構賦值能夠很輕鬆地獲得它。bash

`var` `car = {`
`model:` `'bmw 2018'``,`
`engine: {`
`v6:` `true``,`
`turbo:` `true``,`
`vin: 12345`
`}`
`}`
`const modelAndVIN = ({model, engine: {vin}}) => {`
`console.log(`model: ${model} vin: ${vin}`);`
`}`
`modelAndVIN(car);` `// => model: bmw 2018 vin: 12345`
複製代碼

3.3 合併對象

ES6帶來了擴展運算符(...)。它通常被用來解構數組,但你也能夠用它處理對象。
接下來,咱們使用擴展運算符來展開一個新的對象,第二個對象中的屬性值會改寫第一個對象的屬性值。好比object2的b和c就會改寫object1的同名屬性。數據結構

`let object1 = { a:1, b:2,c:3 }`
`let object2 = { b:30, c:40, d:50}`
`let merged = {…object1, …object2}` `//spread and re-add into merged`
`console.log(merged)` `// {a:1, b:30, c:40, d:50}`
複製代碼

4. Sets

4.1 使用Set實現數組去重

在ES6中,由於Set只存儲惟一值,因此你可使用Set刪除重複項。

`let arr = [1, 1, 2, 2, 3, 3];`
`let deduped = [...``new` `Set(arr)]` `// [1, 2, 3]`
複製代碼

4.2 對Set使用數組方法

使用擴展運算符就能夠簡單的將Set轉換爲數組。因此你能夠對Set使用Array的全部原生方法。
好比咱們想要對下面的Set進行filter操做,獲取大於3的項。

`let mySet =` `new` `Set([1,2, 3, 4, 5]);`
`var` `filtered = [...mySet].filter((x) => x > 3)` `// [4, 5]`
複製代碼

5. 數組解構

有時候你會將函數返回的多個值放在一個數組裏。咱們可使用數組解構來獲取其中每個值。

5.1 數值交換

`let param1 = 1;`
`let param2 = 2;`
`//swap and assign param1 & param2 each others values`
`[param1, param2] = [param2, param1];`
`console.log(param1)` `// 2`
`console.log(param2)` `// 1`
複製代碼

5.2 接收函數返回的多個結果

在下面的代碼中,咱們從/post中獲取一個帖子,而後在/comments中獲取相關評論。因爲咱們使用的是async/await,函數把返回值放在一個數組中。而咱們使用數組解構後就能夠把返回值直接賦給相應的變量。

`async` `function` `getFullPost(){`
`return` `await Promise.all([`
`fetch(``'/post'``),`
`fetch(``'/comments'``)`
`]);`
`}`
`const [post, comments] = getFullPost();`
歡迎加入全棧開發交流划水交流圈:582735936
面向划水1-3年前端人員
幫助突破划水瓶頸,提高思惟能力
複製代碼

什麼是ES6?

ECMAScript 6(如下簡稱ES6)是JavaScript語言的下一代標準,已經在2015年6月正式發佈了。Mozilla公司將在這個標準的基礎上,推出JavaScript 2.0。

ECMAScript和JavaScript究竟是什麼關係?不少初學者會感到困惑,簡單來講,ECMAScript是JavaScript語言的國際標準,JavaScript是ECMAScript的實現。

1、let和const

在JavaScript中我們之前主要用關鍵var來定義變量,ES6以後,新增了定義變量的兩個關鍵字,分別是let和const。
對於變量來講,在ES5中var定義的變量會提高到做用域中全部的函數與語句前面,而ES6中let定義的變量則不會,let聲明的變量會在其相應的代碼塊中創建一個暫時性死區,直至變量被聲明。
let和const都可以聲明塊級做用域,用法和var是相似的,let的特色是不會變量提高,而是被鎖在當前塊中。

一個很是簡單的例子:

`function` `test() {`
`if``(``true``) {`
`console.log(a)``//TDZ,俗稱臨時死區,用來描述變量不提高的現象`
`let a = 1`
`}`
`}`
`test()` `// a is not defined`
`function` `test() {`
`if``(``true``) {`
`let a = 1`
`}`
`console.log(a)`
`}`
`test()` `// a is not defined`
複製代碼

惟一正確的使用方法:先聲明,再訪問。

`function` `test() {`
`if``(``true``) {`
`let a = 1`
`console.log(a)`
`}`
`}`
`test()` `// 1`
歡迎加入全棧開發交流划水交流圈:582735936
面向划水1-3年前端人員
幫助突破划水瓶頸,提高思惟能力
複製代碼

const

聲明常量,一旦聲明,不可更改,並且常量必須初始化賦值。
const雖然是常量,不容許修改默認賦值,但若是定義的是對象Object,那麼能夠修改對象內部的屬性值。

`const type = {`
`a: 1`
`}`
`type.a = 2` `//沒有直接修改type的值,而是修改type.a的屬性值,這是容許的。`
`console.log(type)` `// {a: 2}`
複製代碼

const和let的異同點

相同點:const和let都是在當前塊內有效,執行到塊外會被銷燬,也不存在變量提高(TDZ),不能重複聲明。

不一樣點:const不能再賦值,let聲明的變量能夠重複賦值。
const實際上保證的,並非變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,所以等同於常量。但對於複合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針,const只能保證這個指針是固定的(即老是指向另外一個固定的地址),至於它指向的數據結構是否是可變的,就徹底不能控制了。所以,將一個對象聲明爲常量必須很是當心。

塊級做用域的使用場景

除了上面提到的經常使用聲明方式,咱們還能夠在循環中使用,最出名的一道面試題:循環中定時器閉包的考題
for循環中使用var聲明的循環變量,會跳出循環體污染當前的函數。

`for``(``var` `i = 0; i < 5; i++) {`
`setTimeout(() => {`
`console.log(i)` `//5, 5, 5, 5, 5`
`}, 0)`
`}`
`console.log(i)` `//5 i跳出循環體污染外部函數`
`//將var改爲let以後`
`for``(let i = 0; i < 5; i++) {`
`setTimeout(() => {`
`console.log(i)` `// 0,1,2,3,4`
`}, 0)`
`}`
`console.log(i)``//i is not defined i沒法污染外部函數`
複製代碼

在實際開發中,咱們選擇使用var、let仍是const,取決於咱們的變量是否是須要更新,一般咱們但願變量保證不被惡意修改,而使用大量的const。使用const聲明,聲明一個對象的時候,也推薦使用const,當你須要修改聲明的變量值時,使用let,var能用的場景均可以使用let替代。

symbol

ES6 之前,咱們知道5種基本數據類型分別是Undefined,Null,Boolean,Number以及String,而後加上一種引用類型Object構成了JavaScript中全部的數據類型,可是ES6出來以後,新增了一種數據類型,名叫symbol,像它的名字表露的同樣,意味着獨一無二,意思是每一個 Symbol類型都是獨一無二的,不與其它 Symbol 重複。
能夠經過調用 Symbol() 方法將建立一個新的 Symbol 類型的值,這個值獨一無二,不與任何值相等。

`var` `mySymbol=Symbol();`
`console.log(``typeof` `mySymbol)` `//"symbol"`
複製代碼

2、字符串

ES6字符串新增的方法
UTF-16碼位:ES6強制使用UTF-16字符串編碼。關於UTF-16的解釋請自行百度瞭解。
codePointAt():該方法支持UTF-16,接受編碼單元的位置而非字符串位置做爲參數,返回與字符串中給定位置對應的碼位,即一個整數值。
String.fromCodePoiont():做用與codePointAt相反,檢索字符串中某個字符的碼位,也能夠根據指定的碼位生成一個字符。
normalize():提供Unicode的標準形式,接受一個可選的字符串參數,指明應用某種Unicode標準形式。
在ES6中,新增了3個新方法。每一個方法都接收2個參數,須要檢測的子字符串,以及開始匹配的索引位置。

模板字符串

字符串是JavaScript中基本類型之一,應該算是除了對象以外是使用最爲頻繁的類型吧,字符串中包含了例如substr,replace,indexOf,slice等等諸多方法,ES6引入了模板字符串的特性,用反引號來表示,能夠表示多行字符串以及作到文本插值(利用模板佔位符)。

`// 之前的多行字符串咱們這麼寫:`
`console.log(``"hello world 1\n\` `hello cala"``);`
`// "hello world`
`// hello cala"`
`//有了模板字符串以後`
`console.log(`hello world`
`string text line 2`);`
`// "hello world`
`// hello cala"`
複製代碼

能夠用${}來表示模板佔位符,能夠將你已經定義好的變量傳進括弧中,例如:

`var` `name=``"cala"``;`
`var` `age=22;`
`console.log(`hello,I``'am ${name},my age is ${age}`)` `//hello,I'``am cala,my age is 22`
`includes(str, index):若是在字符串中檢測到指定文本,返回``true``,不然``false``。`
`let t =` `'abcdefg'`
`if``(t.includes(``'cde'``)) {`
`console.log(2)`
`}`
`//true`
`startsWith(str, index):若是在字符串起始部分檢測到指定文本,返回``true``,不然返回``false``。`
`let t =` `'abcdefg'`
`if``(t.startsWith(``'ab'``)) {`
`console.log(2)`
`}`
`//true`
`endsWith(str, index):若是在字符串的結束部分檢測到指定文本,返回``true``,不然返回``false``。`
`let t =` `'abcdefg'`
`if``(t.endsWith(``'fg'``)) {`
`console.log(2)`
`}`
`//true`
複製代碼

若是你只是須要匹配字符串中是否包含某子字符串,那麼推薦使用新增的方法,若是須要找到匹配字符串的位置,使用indexOf()。

3、函數

函數的默認參數

在ES5中,咱們給函數傳參數,而後在函數體內設置默認值,以下面這種方式。

`function` `a(num, callback) {`
`num = num || 6`
`callback = callback ||` `function` `(data) {console.log(``'ES5: '``, data)}`
`callback(num * num)`
`}`
`a()` `//ES5: 36,不傳參輸出默認值`
`//你還能夠這樣使用callback`
`a(10,` `function``(data) {`
`console.log(data * 10)` `// 1000, 傳參輸出新數值`
`})`
複製代碼

在ES6中,咱們使用新的默認值寫法

`function` `a(num = 6, callback =` `function` `(data) {console.log(``'ES6: '``, data)}) {`
`callback(num * num)`
`}`
`a()` `//ES6: 36, 不傳參輸出默認值`
`a(10,` `function``(data) {`
`console.log(data * 10)` `// 1000,傳參輸出新數值`
`})`
複製代碼

4、箭頭函數(=>)

(箭頭函數比較重要,如今簡單提一下,遲一點有空專門寫一篇箭頭函數的文章。)

`const arr = [5, 10]`
`const s = arr.reduce((sum, item) => sum + item)`
`console.log(s)` `// 15`
複製代碼

箭頭函數中this的使用跟普通函數也不同,在JavaScript的普通函數中,都會有一個本身的this值,主要分爲:

普通函數:

一、函數做爲全局函數被調用時,this指向全局對象
二、函數做爲對象中的方法被調用時,this指向該對象
三、函數做爲構造函數的時候,this指向構造函數new出來的新對象
四、還能夠經過call,apply,bind改變this的指向

箭頭函數:

一、箭頭函數沒有this,函數內部的this來自於父級最近的非箭頭函數,而且不能改變this的指向。
二、箭頭函數沒有super
三、箭頭函數沒有arguments
四、箭頭函數沒有new.target綁定。
五、不能使用new
六、沒有原型
七、不支持重複的命名參數。

箭頭函數的簡單理解

一、箭頭函數的左邊表示輸入的參數,右邊表示輸出的結果。

`const s = a => a`
`cosole.log(s(2))` `// 2`
複製代碼

二、在箭頭函數中,this屬於詞法做用域,直接由上下文肯定,對於普通函數中指向不定的this,箭頭函數中處理this無疑更加簡單,以下:

`//ES5普通函數`
`function` `Man(){`
`this``.age=22;`
`return` `function``(){`
`this``.age+1;`
`}`
`}`
`var` `cala=``new` `Man();`
`console.log(cala())``//undefined`
`//ES6箭頭函數`
`function` `Man(){`
`this``.age=22;`
`return` `() =>` `this``.age+1;`
`}`
`var` `cala=``new` `Man();`
`console.log(cala())``//23`
複製代碼

三、箭頭函數中沒有arguments(咱們能夠用rest參數替代),也沒有原型,也不能使用new 關鍵字,例如:

`//沒有arguments`
`var` `foo=(a,b)=>{``return` `arguments[0]*arguments[1]}`
`console.log(foo(3,5))`
`//arguments is not defined`
`//沒有原型`
`var` `Obj = () => {};`
`console.log(Obj.prototype);`
`// undefined`
`//不能使用new 關鍵字`
`var` `Obj = () => {``"hello world"``};`
`var` `o =` `new` `Obj();`
`// TypeError: Obj is not a constructor`
複製代碼

四、箭頭函數給數組排序

`const arr = [10, 50, 30, 40, 20]`
`const s = arr.sort((a, b) => a - b)`
`console.log(s)` `// [10,20,30,40,50]`
複製代碼

尾調用優化

尾調用是指在函數return的時候調用一個新的函數,因爲尾調用的實現須要存儲到內存中,在一個循環體中,若是存在函數的尾調用,你的內存可能爆滿或溢出。

ES6中,引擎會幫你作好尾調用的優化工做,你不須要本身優化,但須要知足下面3個要求:

一、函數不是閉包
二、尾調用是函數最後一條語句
三、尾調用結果做爲函數返回

尾調用實際用途——遞歸函數優化
在ES5時代,咱們不推薦使用遞歸,由於遞歸會影響性能。
可是有了尾調用優化以後,遞歸函數的性能有了提高。

`//新型尾優化寫法`
`"use strict"``;`
`function` `a(n, p = 1) {`
`if``(n <= 1) {`
`return` `1 * p`
`}`
`let s = n * p`
`return` `a(n - 1, s)`
`}`
`//求 1 x 2 x 3的階乘`
`let sum = a(3)`
`console.log(sum)` `// 6`
複製代碼

5、ES6對象新增方法

Object.assign()

Object.assign()方法用於將全部可枚舉屬性的值從一個或多個源對象複製到目標對象。它將返回目標對象。
Object.assign 方法只會拷貝源對象自身的而且可枚舉的屬性到目標對象。該方法使用源對象的[[Get]]和目標對象的[[Set]],因此它會調用相關 getter 和 setter。所以,它分配屬性,而不只僅是複製或定義新的屬性。若是合併源包含getter,這可能使其不適合將新屬性合併到原型中。爲了將屬性定義(包括其可枚舉性)複製到原型,應使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。
String類型和 Symbol 類型的屬性都會被拷貝。

合併對象

`var` `o1 = { a: 1 };`
`var` `o2 = { b: 2 };`
`var` `o3 = { c: 3 };`
`var` `obj = Object.assign(o1, o2, o3);`
`console.log(obj);` `// { a: 1, b: 2, c: 3 }`
`console.log(o1);` `// { a: 1, b: 2, c: 3 }, 注意目標對象自身也會改變。`
複製代碼

合併具備相同屬性的對象

`var` `o1 = { a: 1, b: 1, c: 1 };`
`var` `o2 = { b: 2, c: 2 };`
`var` `o3 = { c: 3 };`
`var` `obj = Object.assign({}, o1, o2, o3);`
`console.log(obj);` `// { a: 1, b: 2, c: 3 }`
歡迎加入全棧開發交流划水交流圈:582735936
面向划水1-3年前端人員
幫助突破划水瓶頸,提高思惟能力
複製代碼

6、Map和Set

Map和Set都叫作集合,可是他們也有所不一樣。Set常被用來檢查對象中是否存在某個鍵名,Map集合常被用來獲取已存的信息。
Set是有序列表,含有相互獨立的非重複值。
Array和Set對比
都是一個存儲多值的容器,二者能夠互相轉換,可是在使用場景上有區別。以下:
Array的indexOf方法比Set的has方法效率低下
Set不含有重複值(能夠利用這個特性實現對一個數組的去重)
Set經過delete方法刪除某個值,而Array只能經過splice。二者的使用方便程度前者更優
Array的不少新方法map、filter、some、every等是Set沒有的(可是經過二者能夠互相轉換來使用)
Object和Map對比
Object是字符串-值,Map是值-值
Object鍵爲string類型,Map的鍵是任意類型
手動計算Object尺寸,Map.size能夠獲取尺寸

Map的排序是插入順序
Object有原型,因此映射中有一些缺省的鍵。能夠理解爲Map=Object.create(null)

Set操做集合

`let set =` `new` `Set()`
`// Set轉化爲數組`
`let arr = Array.from(set)`
`let arr = [...set]`
`// 實例屬性(繼承自Set)`
`set.constructor === Set`
`set.size`
`// 操做方法`
`set.add(1)` `// 添加一個值`
`set.``delete``(1)` `//刪除一個值`
`set.has(1)` `//判斷是否有這個值(Array中的indexOf)`
`set.clear()` `//清除全部值`
`// 獲取用於遍歷的成員方法(Set的遍歷順序就是插入順序)`
`set.keys()` `// 返回鍵名的遍歷器`
`set.values()` `// 返回鍵值得遍歷器`
`set.entries()` `// 返回鍵值對的遍歷器`
`set.forEach()` `// 循環遍歷每一個值(和Array的方法一致)`
`for` `(let key of set.keys()){}`
`for` `(let val of set.values()){}`
`for` `(let entry of set.entries()){}`
`// 使用數組方法來處理set值`
`set =` `new` `Set(arr)`
`set =` `new` `Set([...set].map((x) => x = x * 2))`
`set =` `new` `Set([...set].filter((x) => x > 2))`
複製代碼

Map的方法集合

`let map =` `new` `Map()`
`// 實例屬性(繼承自Map)`
`map.constructor === Map`
`map.size`
`// 操做方法`
`map.set(1,2)`
`map.get(1)`
`map.``delete``(1)`
`map.has(1)`
`map.clear()`
`// 遍歷方法`
`map.keys()`
`map.values()`
`map.entries()`
`map.forEach()`
`// Map和數組的轉換`
`map =` `new` `Map([[``'key'``,``'val'``],[2,1]])` `// 要求雙成員數組`
`let arr = [...map]`
`// 值得注意的是Map的鍵是跟內存綁定的`
`map.set([1],` `'s'``)`
`map.get([1])`
`let arr = [1]`
`let arr1 = [1]`
`map.set(arr,` `'s'``)`
`map.get(arr)`
`map.set(arr1,` `'s'``)`
`map.get(arr1)`
複製代碼

7、迭代器(Iterator)

一、entries() 返回迭代器:返回鍵值對

`//數組`
`const arr = [``'a'``,` `'b'``,` `'c'``];`
`for``(let v of arr.entries()) {`
`console.log(v)`
`}`
`// [0, 'a'] [1, 'b'] [2, 'c']`
`//Set`
`const arr =` `new` `Set([``'a'``,` `'b'``,` `'c'``]);`
`for``(let v of arr.entries()) {`
`console.log(v)`
`}`
`// ['a', 'a'] ['b', 'b'] ['c', 'c']`
`//Map`
`const arr =` `new` `Map();`
`arr.set(``'a'``,` `'a'``);`
`arr.set(``'b'``,` `'b'``);`
`for``(let v of arr.entries()) {`
`console.log(v)`
`}`
`// ['a', 'a'] ['b', 'b']`
複製代碼

二、values() 返回迭代器:返回鍵值對的value

`//數組`
`const arr = [``'a'``,` `'b'``,` `'c'``];`
`for``(let v of arr.values()) {`
`console.log(v)`
`}`
`//'a' 'b' 'c'`
`//Set`
`const arr =` `new` `Set([``'a'``,` `'b'``,` `'c'``]);`
`for``(let v of arr.values()) {`
`console.log(v)`
`}`
`// 'a' 'b' 'c'`
`//Map`
`const arr =` `new` `Map();`
`arr.set(``'a'``,` `'a'``);`
`arr.set(``'b'``,` `'b'``);`
`for``(let v of arr.values()) {`
`console.log(v)`
`}`
`// 'a' 'b'`
複製代碼

三、keys() 返回迭代器:返回鍵值對的key

`//數組`
`const arr = [``'a'``,` `'b'``,` `'c'``];`
`for``(let v of arr.keys()) {`
`console.log(v)`
`}`
`// 0 1 2`
`//Set`
`const arr =` `new` `Set([``'a'``,` `'b'``,` `'c'``]);`
`for``(let v of arr.keys()) {`
`console.log(v)`
`}`
`// 'a' 'b' 'c'`
`//Map`
`const arr =` `new` `Map();`
`arr.set(``'a'``,` `'a'``);`
`arr.set(``'b'``,` `'b'``);`
`for``(let v of arr.keys()) {`
`console.log(v)`
`}`
`// 'a' 'b'`
複製代碼

雖然上面列舉了3種內建的迭代器方法,可是不一樣集合的類型還有本身默認的迭代器,在for of中,數組和Set的默認迭代器是values(),Map的默認迭代器是entries()。

for of循環解構

對象自己不支持迭代,可是咱們能夠本身添加一個生成器,返回一個key,value的迭代器,而後使用for of循環解構key和value。

`const obj = {`
`a: 1,`
`b: 2,`
`*[Symbol.iterator]() {`
`for``(let i` `in` `obj) {`
`yield [i, obj[i]]`
`}`
`}`
`}`
`for``(let [key, value] of obj) {`
`console.log(key, value)`
`}`
`// 'a' 1, 'b' 2`
複製代碼

字符串迭代器

`const str =` `'abc'``;`
`for``(let v of str) {`
`console.log(v)`
`}`
`// 'a' 'b' 'c'`
複製代碼

ES6給數組添加了幾個新方法:find()、findIndex()、fill()、copyWithin()

一、find():傳入一個回調函數,找到數組中符合當前搜索規則的第一個元素,返回它,而且終止搜索。

`const arr = [1,` `"2"``, 3, 3,` `"2"``]`
`console.log(arr.find(n =>` `typeof` `n ===` `"number"``))` `// 1`
複製代碼

二、findIndex():傳入一個回調函數,找到數組中符合當前搜索規則的第一個元素,返回它的下標,終止搜索。

`const arr = [1,` `"2"``, 3, 3,` `"2"``]`
`console.log(arr.findIndex(n =>` `typeof` `n ===` `"number"``))` `// 0`
複製代碼

三、fill():用新元素替換掉數組內的元素,能夠指定替換下標範圍。

`arr.fill(value, start, end)`
複製代碼

四、copyWithin():選擇數組的某個下標,從該位置開始複製數組元素,默認從0開始複製。也能夠指定要複製的元素範圍。

`arr.copyWithin(target, start, end)`
`const arr = [1, 2, 3, 4, 5]`
`console.log(arr.copyWithin(3))` `// [1,2,3,1,2] 從下標爲3的元素開始,複製數組,因此4, 5被替換成1, 2`
`const arr1 = [1, 2, 3, 4, 5]`
`console.log(arr1.copyWithin(3, 1))` `// [1,2,3,2,3] 從下標爲3的元素開始,複製數組,指定複製的第一個元素下標爲 1,因此4, 5被替換成2, 3`
`const arr2 = [1, 2, 3, 4, 5]`
`console.log(arr2.copyWithin(3, 1, 2))` `// [1,2,3,2,5] 從下標爲3的元素開始,複製數組,指定複製的第一個元素下標爲1,結束位置爲2,因此4被替換成2`
複製代碼

ES6中類class、Promise與異步編程、代理(Proxy)和反射(Reflection)API,這幾塊內容比較複雜,之後有機會再詳細寫。

相關文章
相關標籤/搜索