🟨
JavaScript
12 道题目
难度筛选:
闭包是指一个函数能够访问其外部函数作用域中的变量,即使外部函数已经执行完毕。
示例:
应用场景:数据私有化、柯里化、防抖节流、模块模式。
示例:
function outer() {
let count = 0;
return function inner() {
return ++count;
}
}
const fn = outer();
fn(); // 1
fn(); // 2应用场景:数据私有化、柯里化、防抖节流、模块模式。
查看答案即标记为已答
JavaScript 是单线程语言,通过事件循环实现异步非阻塞。
执行顺序:
1. 执行同步代码(调用栈)
2. 清空微任务队列(Promise.then、MutationObserver、queueMicrotask)
3. 取一个宏任务执行(setTimeout、setInterval、I/O、UI 渲染)
4. 再次清空微任务队列
5. 循环往复
关键点:微任务优先级高于宏任务,每个宏任务执行后都会清空所有微任务。
执行顺序:
1. 执行同步代码(调用栈)
2. 清空微任务队列(Promise.then、MutationObserver、queueMicrotask)
3. 取一个宏任务执行(setTimeout、setInterval、I/O、UI 渲染)
4. 再次清空微任务队列
5. 循环往复
关键点:微任务优先级高于宏任务,每个宏任务执行后都会清空所有微任务。
查看答案即标记为已答
每个 JS 对象都有一个
继承方式:
1. 原型链继承:
2. 构造函数继承:
3. 组合继承:原型链 + 构造函数
4. ES6 class:
[[Prototype]] 属性指向其原型对象,形成原型链。访问属性时,如果自身没有,会沿着原型链向上查找。继承方式:
1. 原型链继承:
Child.prototype = new Parent()2. 构造函数继承:
Parent.call(this)3. 组合继承:原型链 + 构造函数
4. ES6 class:
class Child extends Parent(语法糖,本质仍是原型链)Object.getPrototypeOf(obj) 可获取对象的原型。 查看答案即标记为已答
| var | let | const | |
|---|---|---|---|
| 作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
| 变量提升 | ✅ 声明+初始化提升 | ❌ 暂时性死区 | ❌ 暂时性死区 |
| 重复声明 | ✅ | ❌ | ❌ |
| 重新赋值 | ✅ | ✅ | ❌ |
建议:优先使用
const,需要重新赋值时用 let,避免使用 var。 查看答案即标记为已答
Promise 有三种状态:
1. pending(进行中)
2. fulfilled(已成功)
3. rejected(已失败)
状态一旦改变不可逆。
链式调用原理:
静态方法:
1. pending(进行中)
2. fulfilled(已成功)
3. rejected(已失败)
状态一旦改变不可逆。
链式调用原理:
.then() 返回一个新的 Promise,因此可以链式调用。fetch('/api')
.then(r => r.json())
.then(data => process(data))
.catch(err => handleError(err))
.finally(() => cleanup())静态方法:
Promise.all、Promise.race、Promise.allSettled、Promise.any 查看答案即标记为已答
防抖:在事件触发 n 秒后才执行,期间重复触发会重新计时。
节流:n 秒内只执行一次。
场景:防抖用于搜索框输入;节流用于滚动事件、拖拽。
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
}
}节流:n 秒内只执行一次。
function throttle(fn, interval) {
let last = 0;
return function(...args) {
const now = Date.now();
if (now - last >= interval) {
last = now;
fn.apply(this, args);
}
}
}场景:防抖用于搜索框输入;节流用于滚动事件、拖拽。
查看答案即标记为已答
浅拷贝:只复制一层,嵌套对象仍为引用。
深拷贝:递归复制所有层级,完全独立。
1.
2.
3. 递归实现:遍历对象属性,引用类型递归拷贝
4. 第三方库:lodash 的
Object.assign({}, obj)、{...obj}深拷贝:递归复制所有层级,完全独立。
1.
JSON.parse(JSON.stringify(obj)) — 无法处理函数、undefined、循环引用2.
structuredClone(obj) — 原生 API,支持循环引用,不支持函数3. 递归实现:遍历对象属性,引用类型递归拷贝
4. 第三方库:lodash 的
_.cloneDeep() 查看答案即标记为已答
== (宽松相等):比较时会进行类型转换。
=== (严格相等):不进行类型转换,类型和值都必须相同。
建议:始终使用
'1' == 1 // true
null == undefined // true
[] == false // true=== (严格相等):不进行类型转换,类型和值都必须相同。
'1' === 1 // false
null === undefined // false建议:始终使用
===,避免隐式类型转换带来的意外行为。 查看答案即标记为已答
class EventEmitter {
events = {};
on(event, fn) {
(this.events[event] ??= []).push(fn);
}
off(event, fn) {
this.events[event] = this.events[event]?.filter(f => f !== fn);
}
emit(event, ...args) {
this.events[event]?.forEach(fn => fn(...args));
}
once(event, fn) {
const wrap = (...args) => { fn(...args); this.off(event, wrap); };
this.on(event, wrap);
}
}应用:Vue 的 EventBus、Node.js 的 EventEmitter、React 状态管理。
查看答案即标记为已答
利用事件冒泡机制,将子元素的事件监听器绑定在父元素上,通过
优点:
1. 减少内存消耗(不需要每个子元素都绑定事件)
2. 动态添加的子元素自动拥有事件处理
示例:
注意:不是所有事件都冒泡(focus、blur),可用捕获阶段或
event.target 判断实际触发的元素。优点:
1. 减少内存消耗(不需要每个子元素都绑定事件)
2. 动态添加的子元素自动拥有事件处理
示例:
ul.addEventListener('click', (e) => {
if (e.target.tagName === 'LI') {
console.log(e.target.textContent);
}
});注意:不是所有事件都冒泡(focus、blur),可用捕获阶段或
focusin/focusout 替代。 查看答案即标记为已答
class MyPromise {
constructor(executor) {
this.status = 'pending';
this.value = undefined;
this.callbacks = [];
const resolve = (val) => {
if (this.status !== 'pending') return;
this.status = 'fulfilled';
this.value = val;
this.callbacks.forEach(cb => cb.onFulfilled(val));
};
const reject = (reason) => { /* 类似 */ };
executor(resolve, reject);
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
const handle = () => {
try {
const result = this.status === 'fulfilled'
? onFulfilled(this.value)
: onRejected(this.value);
resolve(result);
} catch (e) { reject(e); }
};
this.status === 'pending'
? this.callbacks.push({ onFulfilled: handle, onRejected: handle })
: handle();
});
}
} 查看答案即标记为已答
async/await 是 Generator + Promise 的语法糖。async 函数:
• 返回值自动包装为 Promise
• 内部异常会被 catch 捕获
await:
• 暂停 async 函数执行,等待 Promise resolve
•
await promise 等价于 promise.then(result => result)本质转换:
async function fn() {
const a = await fetchA();
const b = await fetchB(a);
return b;
}等价于:
function fn() {
return fetchA()
.then(a => fetchB(a))
.then(b => b);
} 查看答案即标记为已答