JS 中的事件循环(Event Loop)是一种用于管理和调度异步任务执行的机制。它使得 JS 可以处理异步操作,如定时器、事件处理、网络请求等,而不会阻塞主线程的执行。
宏任务(macro tasks)和微任务(micro tasks)是 JavaScript 引擎中用于管理异步任务执行顺序的两种任务类型。
宏任务(Macro tasks) : 是指那些需要在主线程中执行的任务,它们包括但不限于:
ES(ECMAScript) : ES 模块化是由 ECMAScript 标准规定的,属于 JavaScript 语言本身的一部分。它在 ES6(ECMAScript 2015)中被引入,并已成为 JavaScript 的标准模块化方案。
CommonJS :CommonJS 是 Node.js 中使用的模块化规范,最初是为了解决 JavaScript 在服务器端的模块化问题而创建的。虽然它不是 JavaScript 语言的一部分,但在 Node.js 生态系统中得到了广泛应用。 - 语法和特性:
ES 模块 :ES 模块使用 import 和 export 关键字来导入和导出模块。它支持静态解析,模块加载是异步的,模块的引用是动态的。
CommonJS :CommonJS 使用 require() 函数来导入模块,使用 module.exports 或 exports 来导出模块。它是同步加载的,模块的引用是静态的。
在 ES 模块中,export 出去的对象默认是只读的,不能被修改。当一个对象被导出后,在其他模块中引入该对象时,只能读取其属性和方法,而不能修改它们。
ES 模块:ES 模块对循环引用有着严格的限制,当发生循环引用时,ES 模块会将被引用的模块视为尚未准备好,因此会导致循环引用的模块导出一个空的对象或空值。
CommonJS 在处理循环引用时更为宽松,它会在加载模块时记录模块的导出值,即使发生循环引用也不会导致问题。CommonJS 模块系统允许循环引用中的模块导出部分已经准备好的值。
装饰器(Decorator): 装饰器是一种用于修改类、方法、属性或参数的声明性语法。它们以 @ 符号开头,通常放置在类、方法或属性之前,并可以通过添加元数据或修改行为来扩展或修改它们的行为。
符号(Symbol): 符号是 JavaScript 中的一种基本数据类型,用于创建唯一的、不可变的标识符。符号可以用来创建对象的私有成员、隐藏内部实现细节,或用作对象属性的键,以确保属性名称的唯一性。
void: - void 表示函数没有返回值,或者说函数返回的是 undefined。 - 当一个函数没有显式指定返回值类型时,它的返回类型默认为 void。 - 不能对 void 类型的变量赋予除 undefined 以外的值。
never: - never 表示函数永远不会正常返回,或者说函数会抛出异常或无限循环。 - 通常 never 类型用于表示永远不会执行完的函数或抛出异常的函数,或者在类型系统中表示不可能发生的情况。 - 可以将 never 类型赋值给任何其他类型,但是反过来不行。
使用 PureComponent 或 React.memo使用 useCallback 和 useMemo 进行性能优化使用 React.lazy 延迟组件创建
rebase:
git rebase <base>
git checkout <branch>
其中 是要重新应用提交的目标分支, 是重新应用提交的基准点(通常是另一个分支)。这将会将 上的提交按顺序逐个应用到 上,并移动 指向的提交记录。 cherry-pick:
git cherry-pick <commit-hash>
git cherry-pick 用于选择并应用一个或多个提交到当前分支上,它可以用来将某个分支上的特定提交应用到当前分支上,而不需要将整个分支合并过来。
重绘(Repaint) :
重绘是指当元素样式发生变化,但不影响其几何属性(如位置和大小)时,浏览器重新绘制元素的过程。换句话说,重绘只会更新元素的样式,而不会影响元素的布局。
重排(Reflow) :
重排是指当元素的几何属性发生变化,例如尺寸、位置、隐藏或显示等,导致浏览器重新计算元素的几何属性和页面布局的过程。重排可能会导致整个页面的重新布局,对性能有较大影响。
getBoundingClientRect 不会导致重排
父级元素使用了 transform 或 perspective 属性 - 父级元素使用了 overflow: hidden 属性
requestAnimationFrame: requestAnimationFrame 是一个用于在下一次浏览器重绘之前执行指定的回调函数的方法。它通常用于执行与动画相关的任务,以确保动画的流畅性和性能。
调用时机:requestAnimationFrame 的回调函数会在浏览器下一次绘制之前执行,通常在每秒约 60 次的频率下执行,这与浏览器的刷新率相匹配(通常为每秒 60 次)。
用途:requestAnimationFrame 适用于需要在动画中更新界面状态的场景,如实现平滑的动画效果、制作游戏等。
requestIdleCallback:: requestIdleCallback 是一个用于在浏览器空闲时执行指定的回调函数的方法。它通常用于执行一些低优先级的任务,以确保不会影响到页面的交互和动画性能。
调用时机:requestIdleCallback 的回调函数会在浏览器空闲时执行,即在浏览器没有其他任务需要执行时,会尽快执行注册的回调函数。
用途:requestIdleCallback 适用于执行一些低优先级的任务,如执行分析、预加载资源、后台数据同步等。
在 React 中,组件销毁时并不会自动回收 ref。ref 是一个特殊的属性,用于引用组件实例或 DOM 元素,在组件销毁时,ref 引用的对象并不会自动被销毁,而是需要手动进行清理操作。
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
console.log("script start");
setTimeout(function () {
console.log("setTimeout");
}, 0);
async1();
new Promise(function (resolve) {
console.log("promise1");
resolve();
}).then(function () {
console.log("promise2");
});
console.log("script end");
answer:
"script start";
"async1 start";
"async2";
"promise1";
"script end";
"async1 end";
"promise2";
"setTimeout";
Answer:
// Example usage
const urls = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3',
// Add more URLs as needed
];
const limit = 2;
async function concurrentRequests(urls, limit) {
const results = [];
const inFlightRequests = [];
async function makeRequest(url) {
try {
const response = await fetch(url);
const data = await response.json();
results.push(data);
} catch (error) {
results.push({ error: error.message });
}
}
for (let i = 0; i < urls.length; i++) {
const request = makeRequest(urls[i]);
inFlightRequests.push(request);
if (inFlightRequests.length === limit || i === urls.length - 1) {
await Promise.all(inFlightRequests);
inFlightRequests.length = 0;
}
}
return results;
}
concurrentRequests(urls, limit)
.then(results => console.log(results))
.catch(error => console.error(error));