JavaScript的高級(jí)概念和用法詳解
JavaScript語(yǔ)言不斷發(fā)布一些新特性,感覺(jué)要上天的節(jié)奏啊。本文搜集整理了一些它的高級(jí)概念和用法,來(lái)看看你是否都了解?代碼這樣寫(xiě)是不是更優(yōu)雅了?
1. 閉包
閉包是Javascript中的一項(xiàng)重要技術(shù),內(nèi)部函數(shù)始終可以訪(fǎng)問(wèn)其外部函數(shù)的變量和參數(shù),即使在外部函數(shù)返回后也是如此。我們使用閉包來(lái)保護(hù)我們不想向外部范圍公開(kāi)的數(shù)據(jù)。
// <button onclick=”increaseCounter()”>Increase Counter</button> //1. 全局變量,變量會(huì)被意外修改 let counter = 0; function increaseCounter() { counter++; } //2. 局部變量,每次調(diào)用都重置為0 function increaseCounter() { let counter = 0; counter++; } //3. 閉包函數(shù),符合要求 const increaseCounter = (function() { let counter = 0; return function() { counter = counter + 1; console.log(counter); }; })();
2. 函數(shù)綁定
在上下文丟失時(shí),this將無(wú)法被確定,可以通過(guò)函數(shù)綁定解決。
// 1. 與預(yù)期不符,得到undefined let book = { title: ‘Learn JavaScript', printTitle() { console.log(`Book's title: ${this.title}`); } } setTimeout(book.printTitle, 1000); // Book's title: undefined // 2. 利用函數(shù)綁定,符合預(yù)期 let book = { title: ‘Learn JavaScript', printTitle() { console.log(`Book's title: ${this.title}`); } } let printTitle = book.printTitle.bind(book); setTimeout(printTitle, 1000); // Book's title: JavaScript
3.使用命名空間
使用命名空間可以防止代碼沖突。
// 1. move、jump函數(shù)在animal命名空間下,需要通過(guò)animal.move()來(lái)調(diào)用 let animal = { move: () => { console.log(‘Move!'); }, jump: () => { consle.log(‘Jump!'); } }; // 2. 真實(shí)項(xiàng)目中,可能會(huì)按如下方式使用命名空間 if (typeof APP === "undefined") { APP = {}; APP.ANIMAL = {}; } APP.ANIMAL.move = () => { console.log(‘Move'); }; APP.ANIMAL.jump = () => { console.log(‘Jump'); }; APP.ANIMAL.move(); // Move APP.ANIMAL.jump(); // Jump
4. 判斷屬性是否存在
使用in關(guān)鍵字可以判斷對(duì)象中是否存在某個(gè)屬性。
const person = { id: "123", name: "張三" } console.debug("id" in person) //true console.debug("age" in person) //false
5. 解構(gòu)賦值
利用解構(gòu)賦值表達(dá)式,可以將屬性、值從對(duì)象、數(shù)組中取出,賦值給其它變量,非常方便。
const { address: addressLine } = { address: "長(zhǎng)安街20號(hào)", postcode: "518118" }; console.warn(addressLine); // 長(zhǎng)安街20號(hào) const [first, second] = [1, 2, 3, 4] console.warn(first, second) // 1 2 //動(dòng)態(tài)解構(gòu) const extractKey = "postcode" const { [extractKey]: youbian } = { address: "長(zhǎng)安街20號(hào)", postcode: "518118" }; console.log(youbian) //518118
6.遍歷對(duì)象屬性
使用Object.entries可以遍歷對(duì)象的屬性和值。
const data = { address: "長(zhǎng)安街20號(hào)", postcode: "518118" }; Object.entries(data).forEach(([key,value]) => { if (["address", "postcode"].includes(key)) { console.log('key:', key , 'value:', value) } }) //輸出結(jié)果如下 key: address value: 長(zhǎng)安街20號(hào) key: postcode value: 518118
7. 過(guò)濾數(shù)組
利用數(shù)組的filter、some對(duì)數(shù)組進(jìn)行篩選。
const fruits = ["apple", null, "mongo", undefined, ""] const filted = fruits.filter(Boolean) console.debug(filted) //(2) ["apple", "mongo"] const any = fruits.some(Boolean) console.log(any) //true
8. 消除重復(fù)值
const fruits = ["apple", null, "mongo", "apple", ""] const uniqued = [...new Set(fruits)] console.debug(uniqued) //(4) ["apple", null, "mongo", ""]
9. 判斷是否數(shù)組
利用Array.isArray,而不是typeof判斷。
const fruits = ["apple", null, "mongo", "apple", ""] console.debug(typeof fruits) //object console.error(Array.isArray(fruits)) //true
10. 轉(zhuǎn)換數(shù)字和字符串
const text = "12345" console.debug("text:", +text, "typeof:", typeof(+text)) //text:12345 typeof:number const num = 123456 console.debug("number:", num+"", "typeof:", typeof(num+"")) //number:123456 typeof:string
11. 轉(zhuǎn)換為boolean
利用!!運(yùn)算符可以將其它類(lèi)型轉(zhuǎn)換為Boolean類(lèi)型。
console.log(!!null, typeof(!!null)) //false, boolean console.log(!!"", typeof(!!"")) //false, boolean console.log(!!undefined, typeof(!!undefined)) //false, boolean console.log(!!null, typeof(!!null)) //false, boolean console.log(!!true, typeof(!!true)) //true, boolean console.log(!!false, typeof(!!false)) //false, boolean console.log(!!{id:"", name:""}, typeof(!!{id:"", name:""})) //true, boolean
12. 可選鏈
可選鏈 ?. 是一種訪(fǎng)問(wèn)嵌套對(duì)象屬性的安全的方式,可避免在對(duì)象或?qū)傩圆豢捎脮r(shí)拋出異常。由于JavaScript不是類(lèi)型化語(yǔ)言,該特性還是很有用。
//未使用可選鏈接,將拋出異常 const contactInfos = { address: "長(zhǎng)安街20號(hào)" }; console.warn(contactInfos.user.phoneNumber) // 以上語(yǔ)句將報(bào)錯(cuò):Cannot read properties of undefined (reading 'phoneNumber') //使用可選鏈接,將打印undefined const contactInfos = { address: "長(zhǎng)安街20號(hào)" }; console.warn(contactInfos.user?.phoneNumber) // undefined
13. 合并運(yùn)算符
合并運(yùn)算符的寫(xiě)法為兩個(gè)問(wèn)號(hào) ??,對(duì)于該運(yùn)算符連接的兩個(gè)參數(shù),如果第一個(gè)參數(shù)不是 null,也不是undefined,則返回第一個(gè)參數(shù),否則返回第二個(gè)參數(shù)。
const contactInfos = { address: "長(zhǎng)安街20號(hào)" }; console.warn(contactInfos.user?.phoneNumber ?? "") // "" const contactInfos = { address: "長(zhǎng)安街20號(hào)", addressNumber: 0 }; console.warn(contactInfos.addressNumber || undefined) // undefined console.warn(contactInfos.addressNumber ?? undefined) // 0
14. 有條件地添加屬性
使用...擴(kuò)展語(yǔ)法,可以?xún)H當(dāng)某個(gè)條件成立時(shí),才為對(duì)象添加某個(gè)屬性。
const moreInfos = { info: "請(qǐng)開(kāi)車(chē)前往." } return { address: "長(zhǎng)安街20號(hào)", postcode: "518118", ...(moreInfos !== undefined && { moreInfos }) //僅當(dāng)moreInfos不是undefined時(shí),才添加moreInfos屬性 }
15. 異步調(diào)用異常捕獲
以下寫(xiě)法讓處理異步調(diào)用異常的代碼變得更為簡(jiǎn)潔。
const results = await getPosts().catch((err) => { return { type: "error", message: err.message } }); console.warn(results) // { type: "error", message: "cannot get posts from this endpoint" }
16. 弱引用Map
Weakmap不同于Map,它的鍵必須是引用對(duì)象,不能是基礎(chǔ)類(lèi)型,如果沒(méi)有對(duì)該鍵對(duì)象引用時(shí),該對(duì)象將被從Map和內(nèi)存中移除。
const videoSegments = new WeakMap() let options = { id: "1234", timeStart: 1653831957378, size: 10000 } const segment = { data: new Uint8Array(200) } videoSegments.set(options, segment) console.warn(videoSegments.get(options)) // { data: new Uint8Array(200) } //以下當(dāng)options被賦值為null后,該對(duì)象將被移除和回收 options = null console.warn(videoSegments.has(options)) // false, the `options` key object is deleted from the WeakMap
17. 反射
Reflect是一個(gè)全局對(duì)象,它為元編程提供了一些有用的靜態(tài)方法。
const person = { name: 'Bob', [Symbol('email')]: 'bob@evil.com' }; Reflect.get(person, 'name'); // = Bob Reflect.has(person, 'email'); // = true Reflect.has(person, 'phone'); // = false Reflect.getPrototypeOf(person); // = { constructor ... } Reflect.getOwnPropertyDescriptor( person, 'name'); // = { value: 'Bob', writable: true, enumerable: true, configurable: true } Reflect.ownKeys(person); // name, Symbol(email) Reflect.defineProperty(person, 'phone', { writable: true }); Reflect.has(person, 'phone'); // = true Reflect.set(person, 'phone', '123456789'); Reflect.deleteProperty(person, 'phone'); Reflect.has(person, 'phone'); // = false
18. 柯里化
柯里化(Currying)是一種關(guān)于函數(shù)的高階技術(shù),它是指將一個(gè)函數(shù)從可調(diào)用的 f(a, b, c) 轉(zhuǎn)換為可調(diào)用的 f(a)(b)(c)??吕锘粫?huì)調(diào)用函數(shù),它只是對(duì)函數(shù)進(jìn)行轉(zhuǎn)換。
// 完成銀行轉(zhuǎn)賬交易函數(shù),余額+轉(zhuǎn)入金額-費(fèi)用 const transaction = (fee, balance, amount) => ( balance + amout - fee; ); // 簡(jiǎn)單實(shí)現(xiàn)的柯里化函數(shù) const curry = (fn, ...args) => ( (..._arg) => ( fn(...args, ..._arg) ) ); // 復(fù)用了transaction函數(shù)的免交易費(fèi)函數(shù) const freeTransaction = curry(transaction, 0); freeTransaction(10, 90); // = 100
19. 組合
組合是一種技術(shù),其中一個(gè)函數(shù)的結(jié)果被傳遞到下一個(gè)函數(shù),該函數(shù)被傳遞到下一個(gè)函數(shù),依此類(lèi)推......直到執(zhí)行最終函數(shù)并計(jì)算出一些結(jié)果。函數(shù)組合可以由任意數(shù)量的函數(shù)組成。
//f 和 g 都是函數(shù),x 是在它們之間通過(guò)“管道”傳輸?shù)闹? var compose = function(f,g) { return function(x) { return f(g(x)); }; }; var toUpperCase = function(x) { return x.toUpperCase(); }; var exclaim = function(x) { return x + '!'; }; var shout = compose(exclaim, toUpperCase); shout("send in the clowns"); //=> "SEND IN THE CLOWNS!"
// 組合函數(shù) const compose = (...fns) => x => fns.reduce((y, f) => f(y), x); // 原函數(shù) const addFee = amount => amount + 2; const addDiscount = amount => amount - 5; // 函數(shù)組合 const composition = compose(addFee, addDiscount)(100); console.log(composition) //97
到此這篇關(guān)于JavaScript的高級(jí)概念和用法的文章就介紹到這了,更多相關(guān)js高級(jí)用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決layui table表單提示數(shù)據(jù)接口請(qǐng)求異常的問(wèn)題
今天小編就為大家分享一篇解決layui table表單提示數(shù)據(jù)接口請(qǐng)求異常的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09JavaScript實(shí)現(xiàn)簡(jiǎn)單的四則運(yùn)算計(jì)算器完整實(shí)例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單的四則運(yùn)算計(jì)算器,結(jié)合完整實(shí)例形式分析了javascript基于表單相應(yīng)實(shí)現(xiàn)加減乘除數(shù)學(xué)運(yùn)算的操作技巧,需要的朋友可以參考下2017-04-04JS效率個(gè)人經(jīng)驗(yàn)談(8-15更新),加入range技巧
JS效率個(gè)人經(jīng)驗(yàn)談(8-15更新),加入range技巧...2007-01-01javascript實(shí)現(xiàn)瀑布流加載圖片原理
這篇文章主要為大家介紹了javascript實(shí)現(xiàn)瀑布流加載圖片效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-02-02javascript中mouseenter與mouseover的異同
javascript中mouseover和mouseenter的區(qū)別主要在于監(jiān)聽(tīng)對(duì)象的子元素是否觸發(fā)事件。mouseover:鼠標(biāo)移入監(jiān)聽(tīng)對(duì)象中,或者從監(jiān)聽(tīng)對(duì)象的一個(gè)子元素移入另一個(gè)子元素中時(shí)觸發(fā)該事件。mouseenter:鼠標(biāo)移入監(jiān)聽(tīng)對(duì)象時(shí)觸發(fā),在監(jiān)聽(tīng)對(duì)象內(nèi)移動(dòng)不會(huì)觸發(fā)。2017-06-06Javascript 實(shí)現(xiàn)圖片無(wú)縫滾動(dòng)
這篇文章主要介紹了Javascript 實(shí)現(xiàn)圖片無(wú)縫滾動(dòng)的相關(guān)資料,需要的朋友可以參考下2014-12-12微信小程序?qū)崿F(xiàn)點(diǎn)擊返回頂層的方法
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)點(diǎn)擊返回頂層的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07