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