新聞中心
JavaScript語言不斷發(fā)布一些新特性,感覺要上天的節(jié)奏啊。本文搜集整理了一些它的高級概念和用法,來看看你是否都了解?代碼這樣寫是不是更優(yōu)雅了?

1. 閉包
閉包是Javascript中的一項重要技術(shù),內(nèi)部函數(shù)始終可以訪問其外部函數(shù)的變量和參數(shù),即使在外部函數(shù)返回后也是如此。我們使用閉包來保護我們不想向外部范圍公開的數(shù)據(jù)。
//
//1. 全局變量,變量會被意外修改
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ù)綁定
在上下文丟失時,this將無法被確定,可以通過函數(shù)綁定解決。
// 1. 與預期不符,得到undefined
let book = {
title: ‘Learn JavaScript’,
printTitle() {
console.log(`Book’s title: ${this.title}`);
}
}
setTimeout(book.printTitle, 1000); // Book’s title: undefined
// 2. 利用函數(shù)綁定,符合預期
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命名空間下,需要通過animal.move()來調(diào)用
let animal = {
move: () => {
console.log(‘Move!’);
},
jump: () => {
consle.log(‘Jump!’);
}
};
// 2. 真實項目中,可能會按如下方式使用命名空間
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)鍵字可以判斷對象中是否存在某個屬性。
const person = {
id: "123",
name: "張三"
}
console.debug("id" in person) //true
console.debug("age" in person) //false5. 解構(gòu)賦值
利用解構(gòu)賦值表達式,可以將屬性、值從對象、數(shù)組中取出,賦值給其它變量,非常方便。
const { address: addressLine } = { address: "長安街20號", postcode: "518118" };
console.warn(addressLine); // 長安街20號
const [first, second] = [1, 2, 3, 4]
console.warn(first, second) // 1 2
//動態(tài)解構(gòu)
const extractKey = "postcode"
const { [extractKey]: youbian } = { address: "長安街20號", postcode: "518118" };
console.log(youbian) //5181186.遍歷對象屬性
使用Object.entries可以遍歷對象的屬性和值。
const data = { address: "長安街20號", postcode: "518118" };
Object.entries(data).forEach(([key,value]) => {
if (["address", "postcode"].includes(key)) {
console.log('key:', key , 'value:', value)
}
})
//輸出結(jié)果如下
key: address value: 長安街20號
key: postcode value: 5181187. 過濾數(shù)組
利用數(shù)組的filter、some對數(shù)組進行篩選。
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. 消除重復值
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
利用!!運算符可以將其它類型轉(zhuǎn)換為Boolean類型。
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. 可選鏈
可選鏈 ?. 是一種訪問嵌套對象屬性的安全的方式,可避免在對象或?qū)傩圆豢捎脮r拋出異常。由于JavaScript不是類型化語言,該特性還是很有用。
//未使用可選鏈接,將拋出異常
const contactInfos = { address: "長安街20號" };
console.warn(contactInfos.user.phoneNumber)
// 以上語句將報錯:Cannot read properties of undefined (reading 'phoneNumber')
//使用可選鏈接,將打印undefined
const contactInfos = { address: "長安街20號" };
console.warn(contactInfos.user?.phoneNumber) // undefined
13. 合并運算符
合并運算符的寫法為兩個問號 ??,對于該運算符連接的兩個參數(shù),如果第一個參數(shù)不是 null,也不是undefined,則返回第一個參數(shù),否則返回第二個參數(shù)。
const contactInfos = { address: "長安街20號" };
console.warn(contactInfos.user?.phoneNumber ?? "") // ""
const contactInfos = { address: "長安街20號", addressNumber: 0 };
console.warn(contactInfos.addressNumber || undefined) // undefined
console.warn(contactInfos.addressNumber ?? undefined) // 014. 有條件地添加屬性
使用...擴展語法,可以僅當某個條件成立時,才為對象添加某個屬性。
const moreInfos = { info: "請開車前往." }
return {
address: "長安街20號",
postcode: "518118",
...(moreInfos !== undefined && { moreInfos }) //僅當moreInfos不是undefined時,才添加moreInfos屬性
}15. 異步調(diào)用異常捕獲
以下寫法讓處理異步調(diào)用異常的代碼變得更為簡潔。
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,它的鍵必須是引用對象,不能是基礎(chǔ)類型,如果沒有對該鍵對象引用時,該對象將被從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) }
//以下當options被賦值為null后,該對象將被移除和回收
options = null
console.warn(videoSegments.has(options)) // false, the `options` key object is deleted from the WeakMap
17. 反射
Reflect是一個全局對象,它為元編程提供了一些有用的靜態(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'); // = false18. 柯里化
柯里化(Currying)是一種關(guān)于函數(shù)的高階技術(shù),它是指將一個函數(shù)從可調(diào)用的 f(a, b, c) 轉(zhuǎn)換為可調(diào)用的 f(a)(b)(c)??吕锘粫{(diào)用函數(shù),它只是對函數(shù)進行轉(zhuǎn)換。
// 完成銀行轉(zhuǎn)賬交易函數(shù),余額+轉(zhuǎn)入金額-費用
const transaction = (fee, balance, amount) => (
balance + amout - fee;
);
// 簡單實現(xiàn)的柯里化函數(shù)
const curry = (fn, ...args) => (
(..._arg) => (
fn(...args, ..._arg)
)
);
// 復用了transaction函數(shù)的免交易費函數(shù)
const freeTransaction = curry(transaction, 0);
freeTransaction(10, 90); // = 100
19. 組合
組合是一種技術(shù),其中一個函數(shù)的結(jié)果被傳遞到下一個函數(shù),該函數(shù)被傳遞到下一個函數(shù),依此類推......直到執(zhí)行最終函數(shù)并計算出一些結(jié)果。函數(shù)組合可以由任意數(shù)量的函數(shù)組成。
//f 和 g 都是函數(shù),x 是在它們之間通過“管道”傳輸?shù)闹?br>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
網(wǎng)站欄目:現(xiàn)代JavaScript的高級概念和用法
網(wǎng)站路徑:http://www.dlmjj.cn/article/cdddhoh.html


咨詢
建站咨詢
