js版本ES6、ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14[2023]新特性
ES全稱ECMAScript,ECMAScript是ECMA制定的標準化腳本語言。本文講述Javascript[ECMAScript]版本ES6、ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14[2023]的新特性,幫助朋友們更好的熟悉和使用Javascript。
JS1.1(1997)
第一版基于Netscape Navigator 3.0中實現(xiàn)的JAVASCRIPT 1.1
JS1.2(1999)
基于Netscape Navigator 4.0中實現(xiàn)的JavaScript 1.2。添加了正則表達式、更好的字符串處理、新的控制語句、Try/Catch異常處理、更嚴格的錯誤定義、數(shù)字輸出格式以及其他增強功能
ES5(2015)
1.嚴格模式
use strict
2.Object
- getPrototypeOf,返回一個對象的原型
- getOwnPropertyDescriptor,返回某個對象自有屬性的屬性描述符
- getOwnPropertyNames,返回一個數(shù)組,包括對象所有自由屬性名稱集合(包括不可枚舉的屬性)
- hasOwnProperty,給定屬性存在于對象實例中,返回 true
- isPrototypeOf,在原型鏈中出現(xiàn)過的原型,返回 true
- create,創(chuàng)建一個擁有指定原型和若干指定屬性的對象
- defineProperty,為對象定義一個新屬性,或者修改已有的屬性,并對屬性重新設(shè)置 getter 和 setter,這里可以被用作數(shù)據(jù)綁定的對象劫持用途
- defineProperties,在一個對象上添加或修改一個或者多個自有屬性,與 defineProperty 類似
- seal,鎖定對象,阻止修改現(xiàn)有屬性的特性,并阻止添加新屬性,但是可以修改已有屬性的值
- freeze,凍結(jié)對象,阻止對對象的一切操作和更改,凍結(jié)對象將變成只讀
- preventExtensions,讓一個對象變得不可以擴展,也就是不能再添加新的屬性
- isSealed,判斷對象是否被鎖定
- isFrozen,判斷對象是否被凍結(jié)
- isExtensible,判斷對象是否可以被擴展
- keys,返回一個由給定對象的所有可以枚舉自身屬性的屬性名組成的數(shù)組
3.Array
- Array.isArray,確定某個值到底是不是數(shù)組,不管它在哪個全局執(zhí)行環(huán)境中創(chuàng)建
- push,接收任意數(shù)量的參數(shù),把它們逐個添加到數(shù)組末尾,并返回修改后數(shù)組的長度
- pop,在數(shù)組尾部移除最后一項,減少數(shù)組的 length 值,然后返回移除的項
- shift,移除數(shù)組中的第一項并返回該項,同時將數(shù)組長度減 1
- unshift,在數(shù)組前端添加任意個項,并返回新數(shù)組的長度
- reverse,反轉(zhuǎn)數(shù)組項的順序,返回排序后的數(shù)組
- sort,默認情況下,按升序排序數(shù)組項,返回排序后的數(shù)組
- concat,創(chuàng)建當前數(shù)組的一個副本,將接收到的參數(shù)添加到這個副本的末尾,返回新構(gòu)建的數(shù)組
- join,用指定的字符拼接數(shù)組,返回拼接好的字符串
- slice,基于當前數(shù)組中的一個或多個創(chuàng)建一個新數(shù)組,不影響原始數(shù)組
- splice,根據(jù)傳入?yún)?shù)不同,可以刪除、插入、替換數(shù)組元素,返回一個數(shù)組,該數(shù)組中包含從原始數(shù)組中刪除的項,如果沒有刪除任何項,則返回空數(shù)組
- indexOf,返回根據(jù)給定元素找到的第一個索引值,如果不存在則返回 -1
- lastIndexOf,返回指定元素在數(shù)組中的最后一個索引值,如果不存在則返回 -1
- every ,對數(shù)組中的每一項運行給定函數(shù) ,如果該函數(shù)對每一項都返回 true,則返回 true
- filter,對數(shù)組中的每一項運行給定函數(shù) ,返回該函數(shù)會返回 true 的項組成的數(shù)組
- forEach,對數(shù)組中的每一項運行給定函數(shù),沒有返回值
- map,對數(shù)組中的每一項運行給定函數(shù),返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組
- some,對數(shù)組中的每一項運行給定函數(shù),如果函數(shù)對任一項返回 true,則返回 truereduce,接收一個函數(shù)作為累加器,數(shù)組中的每個值(從左到右)開始縮減,最終縮減為一個值
- reduceRight,接收一個函數(shù)作為累加器,數(shù)組中的每個值(從右到左)開始縮減,最終縮減為一個值
4.String
- charAt,訪問字符串中特定字符,返回給定位置的字符
- charCodeAt,訪問字符串中特定字符,返回給定位置的字符的字符編碼
- concat,將一個或多個字符串拼接起來,返回拼接得到的新字符串
- match,查找匹配的字符串,返回一個數(shù)組
- search,查找匹配的字符串,返回匹配項的索引,沒有找到,返回 -1
- replace,替換字符串
- split,基于指定的分隔符將一個字符串分割成多個字符串,將結(jié)果放在一個數(shù)組中,并返回
- trim,創(chuàng)建一個字符串的副本,刪除前置及后綴的所有空格,然后返回結(jié)果
- localeCompare,比較兩個字符串
- slice,返回被操作字符串的一個子字符串
- substr,返回被操作字符串的一個子字符串
- substring,返回被操作字符串的一個子字符串
注意:slice、substr、substring 都接受一個或兩個參數(shù),第一個參數(shù)指定字符串的開始位置,第二個參數(shù)表示子字符串到哪里結(jié)束,slice 和 substring 的第二個參數(shù)指定的是子字符串的最后一個字符后面的位置,substr 第二個參數(shù)指定的是返回的字符個數(shù),如果沒有傳遞第二個參數(shù),則將字符串的末尾作為結(jié)束位置。
5.Function
- arguments.callee,該屬性是一個指針,指向擁有這個 arguments 對象的函數(shù)
- arguments.caller,該屬性保存著調(diào)用當前函數(shù)的函數(shù)的引用
- apply,在特定的作用域中調(diào)用函數(shù),第一個參數(shù)是在其中運行函數(shù)的作用域,第二個是參數(shù)數(shù)組
- call,在特定的作用域中調(diào)用函數(shù),第一個參數(shù)是在其中運行函數(shù)的作用域,其余參數(shù)直接傳遞給函數(shù)
- bind,創(chuàng)建一個函數(shù)的實例,其 this 值會被綁定到傳給 bind 函數(shù)的值
6.JSON
- JSON.parse,解析字符串為 JSON 對象
- JSON.stringify,解析 JSON 對象為字符串
- JSON.valueOf,獲取某個JSON 對象中的值
- JSON.toString,被調(diào)用時,會調(diào)用 Object 原型上的 toString 方法,會獲的 JSON 對象的值并轉(zhuǎn)為字符串,如果沒有具體的值,則返回原型數(shù)組
- JSON.toLocaleString,也是Object 原型上的方法,經(jīng)常會返回與 toString 相同內(nèi)容,但是對于 Date 對象,則會返回格式化的時間字符串
7.其他
- Date.now,返回當前時間戳
- Date.toJSON,將 Date 對象轉(zhuǎn)換為字符串,格式為 JSON 日期
- Math.min,確定一組數(shù)值中的最小值
- Math.max,確定一組數(shù)值中的最大值
- Math.random,返回大于 0 小于 1 的一個隨機數(shù)
- Number.prototype.toFixed,按照指定的小數(shù)位返回數(shù)值的字符串表示
ES6(2015)
1. 類(class)
class Man { constructor(name) { this.name = '你好世界'; } console() { console.log(this.name); } } const man = new Man('你好世界'); man.console(); // 你好世界
2. 模塊化(ES Module)
// 模塊 A 導出一個方法 export const sub = (a, b) => a + b; // 模塊 B 導入使用 import { sub } from './A'; console.log(sub(1, 2)); // 3
3. 箭頭(Arrow)函數(shù)
const func = (a, b) => a + b; func(1, 2); // 3
4. 函數(shù)參數(shù)默認值
function foo(age = 25,){ // ...}
5. 模板字符串
const name = '你好世界'; const str = `Your name is ${name}`;
6. 解構(gòu)賦值
let a = 1, b= 2; [a, b] = [b, a]; // a 2 b 1
7. 延展操作符
let a = [...'hello world']; // ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]
8. 對象屬性簡寫
const name='你好世界', const obj = { name };
9. Promise
Promise 代表一個異步操作的執(zhí)行返回狀態(tài),這個執(zhí)行返回狀態(tài)在 Promise 對象創(chuàng)建時是未知的,它允許為異步操作的成功或失敗指定處理方法。
9.1 Promise 的狀態(tài)有三種
- Fulfilled,表示 Promise 執(zhí)行成功
- Rejected,表示 Promise 執(zhí)行失敗
- Pending,表示 Promise 正在執(zhí)行中
9.2 Promise 對象有兩個特點
- 對象的狀態(tài)不受外界影響
- 一旦狀態(tài)改變就不會再變,任何時候都可以得到這個結(jié)果
9.3 缺點
- 無法取消 Promise,一旦新建它就會立即執(zhí)行,無法中途取消
- 如果不設(shè)置回調(diào)函數(shù),Promise 內(nèi)部拋出的錯誤不會反應(yīng)到外部
- 當處于 Pending 狀態(tài)時,無法得知目前進展到哪一個階段(剛開始還是即將完成)
9.4 基本用法
var promise = new Promise(function(resolve, reject) { // ... some code if ( /*異步操作成功*/ ) { resolve(value) } else { reject(error) } }) promise.then(function(value) { // success }, function(error) { // failure })
9.5 Promise 實例方法
- Promise.prototype.then(),為 Promise 實例添加狀態(tài)改變時的回調(diào)函數(shù),返回一個新的 Promise 實例
- Promise.prototype.catch(),用于指定發(fā)生錯誤時的回調(diào)函數(shù),返回一個新的 Promise 實例
- Promise.prototype.done(),總是處于回調(diào)鏈的尾端,保證捕捉到任何可能出現(xiàn)的錯誤
- Promise.prototype.finally(),用于指定不管 Promise 對象最后狀態(tài)如何都會執(zhí)行的操作。
finally 與 done 的最大區(qū)別在于:finally 接受一個普通的回調(diào)函數(shù)作為參數(shù),該函數(shù)不管怎樣都必須執(zhí)行。
9.6 Promise 對象方法
- Promise.all(),將多個 Promise 實例包裝成一個新的 Promise 實例。
var p = Promise.all([p1, p2, p3])
p 的狀態(tài)由 p1,p2,p3 決定:
第一,只有 p1,p2,p3 的狀態(tài)都編程 Fulfilled,p 的狀態(tài)才會變成 Fulfilled,此時p1,p2,p3 的返回值組成一個數(shù)組,傳遞給 p 的回調(diào)函數(shù)。
第二,只要 p1,p2,p3 中有一個被 Rejected,p 的狀態(tài)就變成 Rejected,此時第一個被 Rejected 的實例的返回值會傳遞給 p 的回調(diào)函數(shù)
- Promise.race(),將多個 Promise 實例包裝成一個新的 Promise 實例。
var p = Promise.race([p1, p2, p3])
只要 p1,p2,p3 中有一個實例率先改變狀態(tài),p 的狀態(tài)就跟著改變,那個率先改變的 Promise 實例的返回值就傳遞給 p 的回調(diào)函數(shù)。
- Promise.resolve(),將現(xiàn)有對象轉(zhuǎn)為 Promise 對象,狀態(tài)為 Resolved
- Promise.reject(),將現(xiàn)有對象轉(zhuǎn)為 Promise 對象,狀態(tài)為 Rejected
Promise.resolve().then(() => { console.log(2); }); console.log(1); // 先打印 1 ,再打印 2
10. let和const
let name = '你好世界'; const arr = [];
11. 數(shù)組的新特性
ES6 為數(shù)組內(nèi)置對象添加了較多的新特性,主要包括 ... 復制數(shù)組和新增的數(shù)組 API。
const arr = [1, 2, 3] const newArr = [...arr] //[1, 2, 3]
注意:這里 ... 進行的數(shù)組復制是淺拷貝。
ES6 數(shù)組的新增方法:
- Array.from,用于將類數(shù)組對象(包括 [array-like object] 和可遍歷對象)轉(zhuǎn)化為真正的數(shù)組
- Array.of,可以將傳入的一組參數(shù)值轉(zhuǎn)換為數(shù)組
- Array.prototype.copyWithin,可以在當前數(shù)組內(nèi)部將指定位置的數(shù)組項復制到其他位置,然后返回當前數(shù)組,使用 copyWithin 方法會修改當前數(shù)組
- Array.prototype.fill,使用給定值,填充一個數(shù)組,會改變原來的數(shù)組
- Array.prototype.find,用于找出第一個符合條件的數(shù)組元素,有點類似于 filter
- Array.prototype.findIndex,用來返回某個特定數(shù)組元素在數(shù)組中的位置
- Array.prototype.entries,對數(shù)組中鍵值對進行遍歷
- Array.prototype.keys,對數(shù)組鍵名進行遍歷
- Array.prototype.values,對數(shù)組鍵值進行遍歷
- for...of 循環(huán)進行遍歷
- Array.prototype[Symbol.iterator],用來獲取遍歷數(shù)組對象的迭代器
11. 函數(shù)參數(shù)
ES6 對函數(shù)參數(shù)進行了新的設(shè)計,主要添加了默認參數(shù)、不定參數(shù)和擴展參數(shù):
// 默認參數(shù) function sayHi(name = 'zhangsan') { console.log(`Hello ${name}`) } sayHi() // Hello zhangsan // 不定參數(shù) function sayHi(...name) { console.log(name.reduce((a, b) => `Hello ${a} $`)) } sayHi('zhangsan', 'lisi') // 擴展參數(shù) let name = ['zhangsan', 'lisi'] function sayHi(name1, name2) { console.log(`Hello ${name1} ${name2}`) } sayHi(...name)
不定參數(shù)和擴展參數(shù)可以認為恰好是相反的兩個模式,不定參數(shù)是使用數(shù)組來表示多個參數(shù),擴展參數(shù)則是將多個參數(shù)映射到一個數(shù)組。
需要注意:不定參數(shù)的 ... 和數(shù)組復制的 ... 是有區(qū)別的,不定參數(shù)可以使用函數(shù)的形參來表示所有的參數(shù)組成的列表。以前的 arguments 變量也有類似的作用,但是 arguments 不是真正的數(shù)組,除了存放參數(shù)的列表外,arguments 還有 length 屬性,嚴格來說 arguments 是一個類數(shù)組對象,而不定參數(shù)則是一個完全的數(shù)組,這也是不定參數(shù)相對于 arguments 的優(yōu)勢,更加方便我們使用,所以建議使用不定參數(shù)來代替 arguments。
12. 集合類型 Map + Set + WeakMap + WeakSet
12.1 Set
Set 本身是一個構(gòu)造函數(shù) ,用來生成 Set 數(shù)據(jù)結(jié)構(gòu),Set 類似于數(shù)組(但它不是數(shù)組),Set 的成員的值都是唯一的,沒有重復的值,也常用它來去重(不可以傳遞對象)。像 Set 加入值的時候,不會發(fā)生類型轉(zhuǎn)換,所以 5 和 “5” 是兩個不同的值。
const arr = new Set([1, 2, 3, 4, 5, 5, 5, 5]) console.log(arr) //[1, 2, 3, 4, 5] console.log(arr.size) //5
操作方法:
- add(value),添加某個值,返回 Set 結(jié)構(gòu)本身
- delete value,刪除某個值,返回一個布爾值,表示刪除是否成功
- has(value),返回一個布爾值,表示該值是否為 Set 成員
- clear(),清除所有成員,沒有返回值
遍歷方法:
- keys(),返回鍵名的遍歷器
- values(),返回鍵值的遍歷器
- entries(),返回鍵值對的遍歷器
- forEach(),使用回調(diào)函數(shù)遍歷每個成員
12.2 WeakSet
WeakSet 結(jié)構(gòu)與 Set 類似,也是不重復的值的集合,但是,它與 Set 有兩個區(qū)別:
第一,WeakSet 的成員只能是對象,而不能是其他類型的值。
第二,WeakSet 中的對象都是弱引用,即垃圾回收機制 不考慮 WeakSet 對該對象的引用,也就是說,如果其他對象都不在引用該對象,那么垃圾回收機制會自動回收該對象所占用的內(nèi)存,不考慮該對象是否還存在于 WeakSet 中。因此 ES6 規(guī)定 WeakSet 不可遍歷。
12.3 Map
傳統(tǒng)的 JavaScript 的對象(Object),本質(zhì)上是鍵值對的集合(Hash 結(jié)構(gòu)),但是只能用字符串當做鍵,這給它的使用帶來了很大的限制,而 ES6 提供了 Map 數(shù)據(jù)結(jié)構(gòu),它類似于對象,也是鍵值對的集合,但是“鍵” 的范圍不限于字符串,各種類型的值(包括對象)都可以當做鍵。也就是說,Object 結(jié)構(gòu)提供了“字符串-值”的對應(yīng),Map 結(jié)構(gòu)提供了“值-值”的對應(yīng),是一種更完善的 Hash 結(jié)構(gòu)實現(xiàn)。Map 的鍵實際上是跟內(nèi)存地址綁定的,只要內(nèi)存地址不一樣,就視為兩個鍵。
操作方法:
- set(key, value),設(shè)置 key 所對應(yīng)的鍵值,返回整個 Map 結(jié)構(gòu) ,如果 key 已經(jīng)有值,則鍵值會被更新,否則就生成該鍵
- get(key),讀取 key 對應(yīng)的鍵值,如果在好不到 key,則返回 undefined
- has(key),返回一個 布爾值,表示某個鍵是否在 Map 數(shù)據(jù)結(jié)構(gòu)中
- delete(key),刪除某個鍵,返回 true,如果刪除失敗,則返回 false
- clear(),清除所有成員,沒有返回值
遍歷方法:
- keys(),返回鍵名的遍歷器
- values(),返回鍵值的遍歷器
- entries(),返回所有成員的遍歷器
- forEach(),遍歷 Map 的所有成員
12.4 WeakMap
WeakMap 結(jié)構(gòu)與 Map 結(jié)構(gòu)類似,也用于生成鍵值對的集合,但 WeakMap 與 Map 有兩個個區(qū)別:
第一,WeakMap 只接受對象作為鍵名(null 除外),不接受其他類型的值作為鍵名。
第二,WeakMap 的鍵名所指向的對象不計入垃圾回收機制。它的鍵名所引用的對象都是弱引用,即垃圾回收機制不將該引用考慮在內(nèi),因此,只要所引用的對象的其他引用被清除了,垃圾回收機制就會釋放該對象所占用的內(nèi)存。也就是說, 一旦不再需要,WeakMap 里面的鍵名對象和所對應(yīng)的鍵值對會自動消失,不用手動刪除引用?;旧希绻雽ο笾刑砑訑?shù)據(jù)又不想干擾垃圾回收機制,便可以使用 WeakMap。一個典型的應(yīng)用場景是,在網(wǎng)頁的 DOM 元素上添加數(shù)據(jù)時就可以使用 WeakMap 結(jié)構(gòu),當該 DOM 元素被清除,其對應(yīng)的 WeakMap 記錄就會自動被移除。
注意:WeakMap 的專用場景就是它的鍵所對應(yīng)的對象可能會在將來消失,WeakMap 結(jié)構(gòu)有助于防止內(nèi)存泄露。但是,WeakMap 弱引用的只是鍵名而不是鍵值,鍵值依然是正常引用的。
13. Symbol 類型
ES6 引入了一種新的原始數(shù)據(jù)類型 Symbol,表示獨一無二的值,它是 JavaScript 語言的第 7 種數(shù)據(jù)類型,前 6 種分別是:Undefined、Null、Boolean、String、Number 和 Object。
Symbol 值通過 Symbol 函數(shù)生成,一般作為屬性鍵值,并且能避免對象屬性鍵的命名沖突。也就是說,對象的屬性名現(xiàn)在可以有兩種類型:一種是原來就有的字符串,另一種就是新增的 Symbol 類型。只要屬性名屬于 Symbol 類型,就是獨一無二的,可以保證不會與其他屬性名產(chǎn)生沖突。
let s = Symbol('foo') typeof s //"symbol"
注意:
Symbol 函數(shù)前不能使用 new 命令,否則會報錯,這是因為生產(chǎn)的 Symbol 是一個原始類型的值,不是對象。也就是說,由于 Symbol 值不是對象,所以不能添加屬性。基本上,它是一種類似于字符串的數(shù)據(jù)類型。
Symbol 函數(shù)的參數(shù)只表示對當前 Symbol 值的描述,因此相同參數(shù)的 Symbol 函數(shù)的返回值是不相等的。
Symbol 值作為對象屬性名時不能使用點運算符:
let s = Symbol() let obj = { [s]: function() { console.log('Hello') } } obj[s]() // 'Hello'
Symbol 做為屬性名,該屬性不會出現(xiàn)在 for...in,for...of 循環(huán)中,也不會被 Object.keys()、Object.getOwnpropertyNames() 返回,但它也不是私有屬性,Object.getOwnPropertySymbols() 可以獲取指定對象的所有 Symbol 屬性名。 Object.getOwnPropertySymbols() 返回一個數(shù)組,成員是當前對象的所有用作屬性名的 Symbol 值。
Proxy
Proxy 用于修改某些操作的默認行為,可以用來攔截某個對象的屬性訪問方法,然后重載對象的 “ . ” 運算符。
Proxy 可以理解成在目標對象前架設(shè)一個“攔截”層,外界對該對象的訪問都必須先通過這層攔截,因此提供了一種機制可以對外界的訪問進行過濾和改寫。
let object = new Proxy({}, { get: function(target, key, receiver) { console.log(`getting ${key}`) return Reflect.get(target, key, receiver) }, set: function(target, key, value, receiver) { console.log(`setting ${key}`) return Reflect.set(target, key, value, receiver) } })
對比 Object.defineProperty 方法:
let object = {}, value Object.defineProperty(object, 'value', { get: function() { console.log('getting value') return value }, set: function(newValue) { value = newValue console.log('setting: ' + newValue) }, enumerable: true, configurable: true })
Reflect
Reflect 對象的設(shè)計目的有以下幾個:
第一,將 Object 對象的一些明顯屬于語言內(nèi)部的方法(如 Object.defineProperty)放到 Reflect 對象上,現(xiàn)階段,某些方法同時在 Object 和 Reflect 對象上部署,未來新的方法只在 Reflect 對象上部署。也就是說,從 Reflect 對象上可以獲得語言內(nèi)部的方法。
第二,修改某些 Object 方法的返回結(jié)果,讓其變得更加合理。
第三,讓 Object 操作都編程函數(shù)行為,某些 Object 操作是命令式,比如 name in obj 和 delete obj [name],而 Reflect.has(obj, name) 和 Reflect.deleteProperty(obj, name) 讓它們變成了函數(shù)行為。
第四,Reflect 對象的方法與 Proxy 對象的方法一一對應(yīng),只要是 Proxy 對象的方法,就能在 Reflect 對象上找到對應(yīng)的方法,這就是 Proxy 對象可以方便的調(diào)用對應(yīng)的 Reflect 方法來完成默認行為,作為修改行為的基礎(chǔ)。也就是說,無論 Proxy 怎么修改默認行為,我們總可以在 Reflect 上獲取到默認行為。
Iterator
Iterator即迭代器,它是一種接口,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供了統(tǒng)一的訪問機制,換句話說,只要有任何數(shù)據(jù)結(jié)構(gòu)部署了迭代接口,就可以使用統(tǒng)一的方式的來遍歷它。
實現(xiàn)可迭代接口的數(shù)據(jù)結(jié)構(gòu),一般都自身實現(xiàn)或繼承了以Symbol.iterator
屬性的,就屬于可迭代對象。Symbol.iterator
屬性本身是一個函數(shù),就是當前數(shù)據(jù)結(jié)構(gòu)默認的遍歷器生成函數(shù)。
一個包含next()
方法的對象,才可以稱為一個迭代對象。next()
對象的會有返回一個對象,對象中包含兩個值,如下所示:
value
:迭代器返回的任何JavaScript
值。done
為true
時可省略。done
:一個布爾值,為false
時表示迭代未停止,為true
時立即停止迭代器,且可以省略value
的值。
JavaScript原生提供的迭代器接口如下圖所示:
Generator
Generator是ES2015中提供的一種異步編程解決方案,定義Generator函數(shù)在function
關(guān)鍵字和函數(shù)名中間使用*
星號,函數(shù)內(nèi)部使用yield
關(guān)鍵字定義不同的狀態(tài)。
示例代碼如下:
function* testGenerator() { // yield定義一個狀態(tài) yield '一碗周' yield 'es新特性' return 'generator' // 終結(jié)Generator,后面即使有yield關(guān)鍵字也無效 } const g = testGenerator() // 返回 Generator 對象,通過next()方法移動狀態(tài) g.next() /* { value: '一碗周', done: false } */ g.next() /* { value: 'es新特性', done: false } */ g.next() /* { value: 'generator', done: true } */
ES7(2016)
1. 冪指數(shù)操作符
增加了冪指數(shù)操作符來進行冪指數(shù)運算:
console.log(2 ** 3) // 8
x ** y 產(chǎn)生的結(jié)果等同于 Math.pow(x, y)
2. Array.prototype.includes
這個數(shù)組方法主要用來判斷數(shù)組中是否包含某個元素:
let num = [1, 2, 3, 4, 5] console.log(num.includes(1)) // true
ES8(2017)
1. 異步函數(shù) async/await
async 函數(shù)返回一個 Promise 對象,可以使用 then 方法添加回調(diào)函數(shù)。當函數(shù)執(zhí)行的時候,一旦遇到 await 就會先返回,等到異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語句。
function timeout(ms) { return new Promise(resolve => { setTimeout(resolve, ms) }) } async function asyncPrint(value, ms) { await timeout(ms) console.log(value) } asyncPrint('Hello', 300)
上訴代碼指定 300ms 后輸出 Hello。
async 函數(shù)返回一個 Promise 對象,async 函數(shù)內(nèi)部 return 語句返回的值,會成為 then 方法回調(diào)函數(shù)的參數(shù):
async function f() { return 'Hello' } f().then(v => console.log(v)) // 'Hello'
async 函數(shù)內(nèi)部拋出錯誤會導致返回的 Promise 對象變成 rejected 狀態(tài),拋出的錯誤對象會被 catch 方法回調(diào)函數(shù)接受到:
async function f() { throw new Error('出錯了') } f().then( v => console.log(v), e => console.log(e) ) // ‘Error: 出錯了'
正常情況下,await 命令后面是一個 Promise 對象,如果不是,會被轉(zhuǎn)為一個立即 resolve 的 Promise 對象。
await 命令后面的 Promise 對象如果變成 rejected 狀態(tài),則 reject 的參數(shù)會被 catch 方法的回調(diào)函數(shù)接收到。
只要一個 await 語句后面的 Promise 變成 rejected,那么整個 async 函數(shù)都會被中斷執(zhí)行。
注意:
- await 命令后面的 Promise 對象的運行結(jié)果可能是 rejected,最好把 await 命令放在 try...catch 中。
- 多個 await 命令后面的異步操作如果不存在繼發(fā)關(guān)系,最好讓它們同時觸發(fā)。
- await 命令只能用在 async 函數(shù)中,如果用在普通函數(shù)中就會報錯。
2. Object.values()
Object.values({a: 1, b: 2, c: 3}); // [1, 2, 3]
3. Object.entries()
Object.entries({a: 1, b: 2, c: 3}); // [["a", 1], ["b", 2], ["c", 3]]
4. Object.getOwnPropertyDescriptors()
5. String padding
// padStart 'hello'.padStart(10); // " hello" // padEnd 'hello'.padEnd(10) "hello "
6. 函數(shù)參數(shù)列表結(jié)尾允許逗號
7. Object.getOwnPropertyDescriptors()
獲取一個對象的所有自身屬性的描述符,如果沒有任何自身屬性,則返回空對象。
8. SharedArrayBuffer對象
SharedArrayBuffer 對象用來表示一個通用的,固定長度的原始二進制數(shù)據(jù)緩沖區(qū),
/** * * @param {*} length 所創(chuàng)建的數(shù)組緩沖區(qū)的大小,以字節(jié)(byte)為單位。 * @returns {SharedArrayBuffer} 一個大小指定的新 SharedArrayBuffer 對象。其內(nèi)容被初始化為 0。 */ new SharedArrayBuffer(10)
9. Atomics對象
Atomics 對象提供了一組靜態(tài)方法用來對 SharedArrayBuffer 對象進行原子操作。
ES9(2018)
1. 異步迭代
await可以和for...of循環(huán)一起使用,以串行的方式運行異步操作
async function process(array) { for await (let i of array) { // doSomething(i); } }
2. Promise.finally()
Promise.resolve().then().catch(e => e).finally();
3. Rest/Spread 屬性
const values = [1, 2, 3, 5, 6]; console.log( Math.max(...values) ); // 6
4. 正則表達式命名捕獲組
const reg = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/; const match = reg.exec('2021-02-23');
5. 正則表達式反向斷言
(?=p)、(?<=p) p 前面(位置)、p 后面(位置) (?!p)、(?<!p>) 除了 p 前面(位置)、除了 p 后面(位置)
(?<=w)
(?<!w)
6. 正則表達式dotAll模式
正則表達式中點.匹配除回車外的任何單字符,標記s改變這種行為,允許行終止符的出現(xiàn)
/hello.world/.test('hello\nworld'); // false
ES10(2019)
1. Array.flat()和Array.flatMap()
flat()
[1, 2, [3, 4]].flat(Infinity); // [1, 2, 3, 4]
flatMap()
[1, 2, 3, 4].flatMap(a => [a**2]); // [1, 4, 9, 16]
2. String.trimStart()和String.trimEnd()
去除字符串首尾空白字符
3. String.prototype.matchAll
matchAll()為所有匹配的匹配對象返回一個迭代器
const raw_arr = 'test1 test2 test3'.matchAll((/t(e)(st(\d?))/g)); const arr = [...raw_arr];
4. Symbol.prototype.description
只讀屬性,回 Symbol 對象的可選描述的字符串。
Symbol('description').description; // 'description'
5. Object.fromEntries()
返回一個給定對象自身可枚舉屬性的鍵值對數(shù)組
// 通過 Object.fromEntries, 可以將 Map 轉(zhuǎn)化為 Object: const map = new Map([ ['foo', 'bar'], ['baz', 42] ]); console.log(Object.fromEntries(map)); // { foo: "bar", baz: 42 }
6. 可選 Catch
ES11(2020)
1. Nullish coalescing Operator(空值處理)
表達式在 ?? 的左側(cè) 運算符求值為undefined或null,返回其右側(cè)。
let user = { u1: 0, u2: false, u3: null, u4: undefined u5: '', } let u2 = user.u2 ?? '用戶2' // false let u3 = user.u3 ?? '用戶3' // 用戶3 let u4 = user.u4 ?? '用戶4' // 用戶4 let u5 = user.u5 ?? '用戶5' // ''
2. Optional chaining(可選鏈)
?.用戶檢測不確定的中間節(jié)點
let user = {} let u1 = user.childer.name // TypeError: Cannot read property 'name' of undefined let u1 = user.childer?.name // undefined
3. Promise.allSettled
返回一個在所有給定的promise已被決議或被拒絕后決議的promise,并帶有一個對象數(shù)組,每個對象表示對應(yīng)的promise結(jié)果
const promise1 = Promise.resolve(3); const promise2 = 42; const promise3 = new Promise((resolve, reject) => reject('我是失敗的Promise_1')); const promise4 = new Promise((resolve, reject) => reject('我是失敗的Promise_2')); const promiseList = [promise1,promise2,promise3, promise4] Promise.allSettled(promiseList) .then(values=>{ console.log(values) });
4. import()
按需導入
5. 新基本數(shù)據(jù)類型BigInt
任意精度的整數(shù)
6. globalThis
- 瀏覽器:window
- worker:self
- node:global
ES12(2021)
1. replaceAll
返回一個全新的字符串,所有符合匹配規(guī)則的字符都將被替換掉
const str = 'hello world'; str.replaceAll('l', ''); // "heo word"
2. Promise.any
Promise.any() 接收一個Promise可迭代對象,只要其中的一個 promise 成功,就返回那個已經(jīng)成功的 promise 。如果可迭代對象中沒有一個 promise 成功(即所有的 promises 都失敗/拒絕),就返回一個失敗的 promise
const promise1 = new Promise((resolve, reject) => reject('我是失敗的Promise_1')); const promise2 = new Promise((resolve, reject) => reject('我是失敗的Promise_2')); const promiseList = [promise1, promise2]; Promise.any(promiseList) .then(values=>{ console.log(values); }) .catch(e=>{ console.log(e); });
3. WeakRefs
使用WeakRefs的Class類創(chuàng)建對對象的弱引用(對對象的弱引用是指當該對象應(yīng)該被GC回收時不會阻止GC的回收行為)
4. 邏輯運算符和賦值表達式
邏輯運算符和賦值表達式,新特性結(jié)合了邏輯運算符(&&,||,??)和賦值表達式而JavaScript已存在的 復合賦值運算符有:
a ||= b //等價于 a = a || (a = b) a &&= b //等價于 a = a && (a = b) a ??= b //等價于 a = a ?? (a = b)
5. 數(shù)字分隔符
數(shù)字分隔符,可以在數(shù)字之間創(chuàng)建可視化分隔符,通過_下劃線來分割數(shù)字,使數(shù)字更具可讀性
const money = 1_000_000_000; //等價于 const money = 1000000000; 1_000_000_000 === 1000000000; // true
ES13(2022)
1.class的擴展
在ES2022中允許我們并不在constructor
中定義類的成員,示例代碼如下:
class C { myName = '一碗周' } /* 兩者是一致的 */ class C { constructor() { myName = '一碗周' } }
如果成員只聲明不初始化它的默認值是undefined。
在ES2022中允許我們使用#
開頭命名的變量作為類的私有成員,示例代碼如下:
class C { #myName = '一碗周' } const c = new C() console.log(#myName) // Private field '#myName' must be declared in an enclosing class
2. await在頂層使用
在ES2022中新增了允許在頂層使用await
,在頂層可以不適用async
函數(shù)進行包裹,示例代碼如下:
import { AsyncFun } from 'module' await AsyncFun() console.log(123)
3. Object.hasOwn()
Object.hasOwn()
方法用于判斷某個對象上是否具有某個屬性,示例代碼如下:
const person = { name: '一碗周', age: 18, } console.log(Object.hasOwn(person, 'name')) // true console.log(Object.hasOwn(person, 'sex')) // false
4. Array.prototype.at()
ES2022中新增的at()
方法,它的作用是獲取數(shù)組中的某個成員,它的參數(shù)是數(shù)組的索引,與直接使用索引的方式不同,它允許我們傳遞負值,等同于從后面倒數(shù),示例代碼如下:
const arr = [1, 2, 3, 4, 5, 6] console.log(arr.at(-1)) // 6 // 等同于 arr[arr.length - 1]
5. d修飾符
正則表達式增加了一個/d
修飾符,當使用正則表達式的exec()
方法時,如果有/d
修飾符,那么結(jié)果會多返回一個indices屬性,用來表示匹配的結(jié)果的在原字符串中的起始index值。示例代碼如下:
const str = 'JavaScript' const r = /a/d const m = r.exec(str) console.log(m.indices[0]) //[ 1, 2 ]
6. 頂層 await
之前await關(guān)鍵字只能在async函數(shù)內(nèi)部使用,在外部使用就會報錯: SyntaxError - SyntaxError: await is only valid in async function;
在ES13 允許在模塊的頂層使用 await, 并且不再需要配合 async函數(shù)使用,它允許模塊充當大型異步函數(shù),使得我們在 ESM 模塊中可以等待資源的加載,只有資源加載完畢之后才會去執(zhí)行當前模塊的代碼。
實際運用:
a、動態(tài)加載模塊
const strings = await import(`/i18n/${navigator.language}`);
這對于開發(fā)/生產(chǎn)拆分、國際化、環(huán)境拆分等非常有用。
b、資源初始化
const connection = await dbConnector();
配合try catch實現(xiàn)依賴回退
let jQuery; try { jQuery = await import('https://cdn-a.com/jQuery'); } catch { jQuery = await import('https://cdn-b.com/jQuery'); }
依賴發(fā)生故障時,可以回退到舊版本,防止程序崩潰。
7. at()
.at()是數(shù)組新增的一個方法,通過傳遞給定索引來獲取數(shù)組元素,這個索引可以是正數(shù)也可以是負數(shù),當索引是正數(shù)時效果和 [] 是一樣的,當索引是負數(shù)時就會從數(shù)組的最后一項開始。
const arr = [1,2,3,4,5]; arr[arr.length-1] // 5 const arr = [1,2,3,4,5]; arr.at(-1) // 5
支持類型
- String
- Array
- Typed Array
ES14(2023)
1. Array.prototype.toSorted
toSorted() 與 Array.prototype.sort() 具有相同的簽名,但它創(chuàng)建一個新的數(shù)組,而不是對原數(shù)組進行操作。
let arr = [5, 4, 2, 3, 1]; arr === arr.sort(); // true - [1, 2, 3, 4, 5] arr === arr.toSorted(); // false - [1, 2, 3, 4, 5]
toSorted() 和 sort() 一樣,接受一個可選參數(shù)作為比較函數(shù)。例如,我們可以使用 toSorted() 創(chuàng)建一個按降序排列的新數(shù)組
const numbers = [10, 5, 2, 7, 3, 9, 1, 6, 4]; const sortedNumbers = numbers.toSorted((a, b) => { return b - a; }); console.log(sortedNumbers); // [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
需要注意的是,toSorted() 也可以應(yīng)用于對象數(shù)組。這種情況下,需要提供一個使用對象上的數(shù)據(jù)的比較函數(shù),因為對象沒有自然的排序方式。
// 比較對象 const objects = [ { name: "John", age: 30 }, { name: "Jane", age: 25 }, { name: "Bill", age: 40 }, { name: "Mary", age: 20 } ]; const sortedObjects = objects.toSorted((a, b) => { return a.name.localeCompare(b.name); }); console.log(sortedObjects); // [{"name":"Bill","age":40},{"name":"Jane","age":25},{"name":"John","age":30},{"name":"Mary","age":20}]
2. Array.prototype.toReversed
與 toSorted() 和 sort() 一樣,toReversed() 是 reverse() 的復制版本。
["a", "b", "c", "d", "e"].toReversed(); // ['e', 'd', 'c', 'b', 'a']
3. Array.prototype.with
新的 with() 方法允許您基于索引修改單個元素,并返回一個新的數(shù)組。因此,如果您知道索引和新值,這個方法非常方便。需要注意的是with() 是 set() 的復制伴侶。
const arr4 = ["I", "am", "the", "Walrus"]; // 用 "Ape Man" 替換字符串 "Walrus"。 const newArr4 = arr4.with(3, "Ape Man"); console.log(newArr4);
4. Array.prototype.findLast
findLast() 方法允許您從數(shù)組中獲取匹配元素的最后一個實例。如果找不到匹配元素,則返回 undefined。下面代碼中提供了一個簡單的示例,我們從數(shù)組中獲取最后一個偶數(shù)。
const arr = [54, 34, 55, 75, 98, 77]; const lastEvenIndex = arr.findLast((element) => { return element % 2 === 0; }); console.log(lastEvenIndex); // 98
findLast() 還支持傳遞一個 "thisArg" 來設(shè)置上下文。也就是說,第二個參數(shù)將告訴第一個參數(shù)函數(shù) this 關(guān)鍵字將引用什么。從下面代碼中看到這一點,我們使用一個自定義對象來找到可以被 5 整除的第一個元素。
const arr6 = [54, 34, 55, 75, 98, 77]; const myObject = { testCase: 5 }; const lastEvenIndex = arr5.findLast((element) => { return element % myObject.testCase === 0; }, myObject); console.log(lastEvenIndex); // 75
5.Array.prototype.findLastIndex
findLastIndex() 的工作方式與 findLast() 相同,只是它返回匹配元素的索引而不是元素本身。例如,下面例子展示如何找到最后一個可以被 6 整除的元素的索引。
代碼清單 8. 使用 findLastIndex() 找到元素的索引 const arr = [54, 34, 55, 75, 98, 77]; arr.findLastIndex(x => x % 6 === 0); // 0
6.Array.prototype.toSpliced
上面新增的所有方法也適用于 TypedArray,但 toSpliced() 這個新的數(shù)組方法只存在于 Array 中。toSpliced() 方法是 splice() 的復制版本,splice()是js中數(shù)組操作常用的方法;
假設(shè)我們有一個顏色數(shù)組,需要在中間插入一些新的顏色(粉紅色和青色)。這會創(chuàng)建一個新數(shù)組,而不是修改原始數(shù)組。
const arr = ["red", "orange", "yellow", "green", "blue", "purple"]; const newArr = arr.toSpliced(2, 1, "pink", "cyan"); console.log(newArr); // ["red", "orange", "pink", "cyan", "green", "blue", "purple"] console.log(newArr[3]); // 'cyan' console.log(arr[3]); // 'green'
7.正式的 shebang 支持
Shebang 是舊式 Unix 術(shù)語,表示井號后跟一個感嘆號:#!(其中 "bang" 是感嘆號的俚語)。
#!/bin/bash echo "Hello, world!"
您可以使用 ./hello.sh 直接運行上面代碼。
您也可以在 JavaScript 中執(zhí)行類似操作,如代碼清單 11 所示。
#!/usr/bin/env node console.log("Hello, world!");
上面例子告訴操作系統(tǒng)使用 node 程序來運行此腳本。只需鍵入 ./hello.js 即可運行它。如果沒有 #!是無法運行的。
Shebang 支持是規(guī)范中已經(jīng)實現(xiàn)并在多種情境下非正式采用的特性之一。
8.Symbol 作為 WeakMap 的鍵
ES14中的最后一個新功能是Symbol 可以作為 WeakMap 的鍵使用。在這之前,WeakMap僅允許對象作為鍵值,新特性更容易創(chuàng)建和共享key。
var map = new WeakMap(); // 創(chuàng)建一個弱映射 function useSymbol(symbol){ doSomethingWith(symbol); var called = map.get(symbol) || 0
上面的例子允許從外部調(diào)用者調(diào)用計數(shù)器,并在不再有引用時釋放映射條目。代碼本身無法知道何時不再需要引用,如果使用普通的 Map,將會導致內(nèi)存泄漏。這是因為即使在調(diào)用它的客戶端不再需要引用時,代碼仍然會保留對該引用的持有。在這種情況下使用 WeakMap,可以確保垃圾回收在不再存在對鍵符號的引用時刪除映射條目。
9. Record 和 Tuple 類型
const person = { name: "John Doe", age: 30, hobbies: ["coding", "reading", "playing guitar"] };
這段代碼定義了一個名為 person 的 Record,其中包含三個元素:姓名、年齡和愛好。name 元素是一個字符串,age 元素是一個整數(shù),hobbies 元素是一個字符串數(shù)組。
以下是 ES14 之后的 ECMAScript 2023 中的元組示例:
const colors = ["red", "green", "blue", "purple"];
此代碼定義了一個名為顏色的元組,其中包含四個元素:紅色、綠色、藍色和紫色。元組的元素現(xiàn)在可以是任何類型的數(shù)據(jù)。
總結(jié)
到此這篇關(guān)于js版本ES6、ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14[2023]新特性的文章就介紹到這了,更多相關(guān)js版本ES6-ES14的新特性集合內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在 JavaScript 中管理 Token 的最佳實踐記錄
文章介紹了在JavaScript中管理Token的最佳實踐,包括Token的作用、存儲方式、代碼實現(xiàn)和安全性考慮,通過示例代碼,展示了如何在不同環(huán)境中動態(tài)設(shè)置Token作用域,并提供了安全存儲和保護Token的方法2024-11-11three.js實現(xiàn)圍繞某物體旋轉(zhuǎn)
本篇文章主要介紹了three.js實現(xiàn)圍繞某物體旋轉(zhuǎn)的示例代碼。具有很好的參考價值,下面跟著小編一起來看下吧2017-01-01javascript內(nèi)置對象Date案例總結(jié)分析
今天總結(jié)javascript內(nèi)置對象Date的使用,并且寫一個重要的網(wǎng)頁倒計時的核心算法案例,有需要的朋友可以借鑒參考下希望能夠有所幫助,祝大家多多進步2022-03-03基于MooTools的很有創(chuàng)意的滾動條時鐘動畫
一款很有創(chuàng)意的時鐘js動畫.是利用系統(tǒng)滾動條來構(gòu)成一個 時:分:秒 的盤. 再利用滾動條的長度變化做過渡動畫.2010-11-11