JavaScript進階之道

NO IMAGE

Python 和 JavaScript 在筆者看來是很相似的語言,本文歸納了 JavaScript 的語言專屬特性。

語言專屬特性

箭頭函數

函數的簡易定義方式,配合高階函數mapfilterreduce實現函數式編程

map – 映射

[1, 2, 3, 4, 5].map(e => e ** 2);
// [1, 4, 9, 16, 25]

filter – 過濾

[1, 2, 3, 4, 5].filter(e => e > 3);
// [4, 5]

reduce – 歸併

[1, 2, 3, 4, 5].reduce((acc, cur) => acc + cur);
// 15

解構賦值

最典型的例子就是 2 數交換

let [a, b] = [b, a];

用擴展運算符可以獲取剩餘的元素

let [first, ...rest] = [1, 2, 3, 4];
first;
// 1
rest;
// [2, 3, 4]

擴展運算符

數據結構的合併

let arr1 = ['kaguya', 'miyuki']
let arr2 = ['chika', 'ishigami']
[...arr1, ...arr2]
// ['kaguya', 'miyuki', 'chika', 'ishigami']
let obj1 = {'name': 'rimuru'}
let obj2 = {'kind': 'slime'}
{...obj1, ...obj2}
// {name: 'rimuru', kind: 'slime'}

函數參數的打包與解包

// 打包
let foo = (...args) => console.log(args);
foo(1, 2);
// [1, 2]
// JS只能打包位置參數,無法正確地打包關鍵詞參數
// foo(name='hayasaka', job='maid')
// ["hayasaka", "maid"] (keyword沒了)
// 解包
let divmod = (a, b) => [Math.floor(a / b), a % b];
let t = [10, 3];
let [quotient, remainder] = divmod(...t);
quotient;
// 商:3
remainder;
// 餘:1

async

async 函數返回隱式的 Promise,是異步代碼的理想的編寫方式

let sleep = time => new Promise(resolve => setTimeout(resolve, time));
async function main() {
console.log(`開始:${new Date()}`);
await sleep(1000);
console.log(`結束:${new Date()}`);
}
main();

假設定義了 3 個異步操作任務

async function task1() {
console.log("task 1 start");
await sleep(1000);
console.log("task 1 end");
}
async function task2() {
console.log("task 2 start");
await sleep(1000);
console.log("task 2 end");
}
async function task3() {
console.log("task 3 start");
await sleep(1000);
console.log("task 3 end");
}

順序執行

async function main() {
const tasks = [task1, task2, task3];
for (let i = 0; i < tasks.length; i++) {
await tasks[i]();
}
}
main();
// task 1 start
// task 1 end
// task 2 start
// task 2 end
// task 3 start
// task 3 end

併發執行

function main() {
const tasks = [task1, task2, task3];
tasks.forEach(task => task());
}
main();
// task 1 start
// task 2 start
// task 3 start
// task 1 end
// task 2 end
// task 3 end

任務完成後執行某操作

async function main() {
await Promise.all([task1(), task2(), task3()]);
console.log("all complete!");
}
main();
// task 1 start
// task 2 start
// task 3 start
// task 1 end
// task 2 end
// task 3 end
// all complete!

Proxy

如果瞭解 Python 類的描述符特性,那麼 Proxy 也會變得很好理解

在 Python 中, 類的描述符可以給類屬性定義相同的存取行為

而 JS 的 Proxy 也差不多,也是給對象屬性定義相同的存取行為(官方說是攔截讀取操作,其實意思也差不多)

以下實現一個簡單的 Proxy,用來在讀寫屬性時驗證屬性的正確性

let validator = {
set: (obj, key, value) => {
if (key === "age") {
if (!Number.isInteger(value)) {
throw new TypeError(`${key} must be an Integer`);
}
if (value > 200) {
throw new RangeError(`${key} must be under 200`);
}
}
obj[key] = value;
return true;
}
};
class Person {
constructor(age) {
this.age = age;
return new Proxy(this, validator);
}
}
let person = new Person((age = 100));
person.age = "young";
// Uncaught TypeError: age must be an Integer
person.age = 201;
// Uncaught RangeError: age must be under 200

相關文章

嚐鮮Vue3之一:瀏覽器中如何斷點調試Vue3源碼

DOM的常用API速查表

一個孤獨中二患者的自白|年度徵文

前端必備的實用工具,都在這裡了