函数¶
function sum(x=0, y=0) {
return x + y;
}
sum(1, 2); // 3
sum(undefined, 2) // 2,x使用默认值
sum(1) // 1,y使用默认值
- 解构式传参
function sum({x=0, y=0}) {
return x + y;
}
sum({x:1, y:2}) // 3
- 扩展运算符
function addNumbers(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
// 使用扩展运算符将数组中的元素展开作为函数的参数
const result = addNumbers(...numbers);
console.log(result); // 输出: 6
匿名函数¶
- 函数表达式
let sum = function(x, y) {
return x + y;
}; // 注意末尾要带分号,表示赋值语句结束
data: function () { pass } 可简写为 data () { pass }
- 箭头函数
ES6 新增
let sum = (x, y) => {
return x + y;
}
// 只有一个 return 语句时,可不写 return,并省略掉花括号
let y = x => x * x;
回调函数¶
函数作为参数,传给另一个函数时被称之为回调函数,早期用于异步
function callback() {
console.log('Hello, JavaScript!');
}
setTimeout(callback, 1000); // 定时器,1000毫秒后,执行callback
console.log('hello');
// hello
// Hello, JavaScript! (1 秒后输出)
闭包¶
函数嵌套,内部函数作为外部函数的返回值
示例:统计 demo 函数被调用次数
- 非闭包实现
let count = 0; // 这里的count是全局变量,有可能会被其它函数修改
function demo() {
count++;
return count;
}
demo(); // 1
demo(); // 2
- 闭包实现,防止变量污染
function demo() {
let count = 0; // 这里的count是局部变量,不会被其它函数修改
return function () {
count++;
return count;
};
}
let addCount = demo();
addCount(); // 1
addCount(); // 2
异步函数¶
ES6 引入了 Promise 用于替代回调函数来实现异步,类似 Python 的 Asyncio
Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)
async/await¶
async/await 是 Promise 的语法糖,让异步编程更易于理解和使用
在一个函数前面加上 async 关键字 ,将它变为异步函数,它的返回值会被自动包装为一个 Promise
await 关键字只能在 async 函数内工作,后接 Promise 对象,等待 Promise 变成 fulfilled 或 rejected
- 示例1
async function helloAwait() {
const value = await hello();
console.log(value);
console.log('hello await');
}
helloAwait()
// Hello, JavaScript async! (1 秒后输出)
// hello await
- 示例2
async function getBaycMetadata(){
const url = `https://ipfs.io/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/1`;
const response = await fetch(url); // fetch() 用于HTTP请求,await 返回数据后才会继续执行下一步
const BaycMetadata = await response.json();
console.log(BaycMetadata);
}
getBaycMetadata()
// image: "ipfs://QmPbxeGcXhYQQNgsC6a36dDyYUcHgMLnGKnF8pVFmGsvqi"
// attributes...
Promise¶
Promise 等价于 Python 中的 Future
// 使用构造函数创建一个 Promise
const promise = new Promise((resolve, reject) => {
// 异步操作,比如:读取文件、网络请求等
// 设置定时器模拟异步操作
setTimeout(() => {
// 成功后返回 resolve() 中的内容,失败可以调用 reject()
resolve('Hello, JavaScript Promise!');
}, 1000)
})
// 用 .then 管理异步代码
// 接受两个回调函数作为可选参数
promise.then(
value => {
// 处理解析值的回调函数
},
error => {
// 处理错误的回调函数
}
) // .then 会返回一个新的 Promise,可以链式调用
.then(
newValue => console.log(newValue)
) // 还可以接catch来处理错误,.catch 返回的依然是 Promise
.catch(
error => console.error(error)
) // 最后还可以接 .finally,无论 Promise 的状态如何都会执行
.finally(
() => {
console.log('finally')
}
);
console.log('hello Promise');
// hello Promise
// Hello, JavaScript Promise! (1 秒后输出)
- 链式 Promise
fetch('https://api.example.com/data') // 返回一个 Promise
.then(response => response.json()) // 返回一个新的 Promise
.then(data => console.log(data)) // 返回一个新的 Promise
.catch(error => console.error(error)); // 返回一个新的 Promise
- 并行 Promise
Promise.all([
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2')
])
.then(([response1, response2]) => Promise.all([response1.json(), response2.json()]))
.then(([data1, data2]) => {
console.log('Data 1:', data1);
console.log('Data 2:', data2);
})
.catch(error => console.error(error));
- Promise API
Promise.reject(reason):返回一个用给定的原因拒绝的 Promise。
Promise.resolve(value):返回一个以给定值解析后的 Promise。如果该值是一个 Promise,返回的 Promise 将具有相同的状态和值。
Promise.race(iterable):返回一个新的 Promise,它在 iterable 中的任何 Promise 解析或拒绝后具有相同的解析值或拒绝原因。
Promise.all(iterable):返回一个新的 Promise,它在 iterable 中的所有 Promise 都解析后解析,或者在 iterable 中的任何 Promise 被拒绝后拒绝。
Promise.any: 与 Promise.race 类似,区别在于只要有一个 Promise 实例变成 fulfilled 状态,包装实例就会变成 fulfilled 状态;所有 Promise 实例都变成 rejected 状态,包装实例才会变成 rejected 状态。
Promise.allSettled(iterable): 有时我们希望等到一组异步操作都结束了,不管每一个操作是成功还是失败,再进行下一步操作。但是,Promise.all 方法只适合所有异步操作都成功的情况,如果有一个操作失败,就无法满足要求。这时我们需要使用 Promise.allSettled 方法。
Event Loop¶
在 JavaScript 的事件循环机制中,任务被分为两种类型:
- 宏任务(Macrotask):由 JavaScript 引擎线程直接执行的任务,包括
整个脚本(main script)
setTimeout 和 setInterval 的回调
setImmediate(Node.js环境)等 - 微任务(Microtask):微任务是在当前宏任务结束后立即执行的任务,包括
Promise 的 then 和 catch 的回调
process.nextTick(Node.js环境)
MutationObserver的回调(浏览器环境)等
执行步骤:
- 从宏任务队列中取出一个任务来执行
- 执行完这个任务后,执行所有的微任务
- 当微任务队列清空后,进入下一次事件循环,执行下一个宏任务
// 宏任务
console.log('script start'); // 微任务
// 宏任务
setTimeout(function() {
console.log('setTimeout'); // 微任务
}, 0);
// 宏任务
Promise.resolve().then(function() {
console.log('promise1'); // 微任务
}).then(function() {
console.log('promise2'); // 微任务
});
// 宏任务
console.log('script end'); // 微任务
// 输出顺序
/*
script start
script end
promise1
promise2
setTimeout
*/
最后更新:
2023-08-15