金九银十面试季,这些JavaScript题你都会吗?本文整理了50道高频面试题,涵盖核心概念和ES6+新特性,助你轻松通关前端面试!
其他面试链接
📚 目录
🎯 JavaScript基础篇
1. JavaScript中的数据类型有哪些?
答案: JavaScript有8种数据类型:
- 基本类型:
undefined、null、boolean、number、string、symbol、bigint - 引用类型:
object
详解:
// 基本类型
let a = undefined;
let b = null;
let c = true;
let d = 42;
let e = "hello";
let f = Symbol('symbol');
let g = 123n; // BigInt
// 引用类型
let h = { name: 'John' };
let i = [1, 2, 3];
let j = function() {};
类型检测:
// typeof 操作符
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (这是JavaScript的一个bug)
console.log(typeof true); // "boolean"
console.log(typeof 42); // "number"
console.log(typeof "hello"); // "string"
console.log(typeof Symbol()); // "symbol"
console.log(typeof 123n); // "bigint"
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"
// instanceof 操作符
console.log([] instanceof Array); // true
console.log({} instanceof Object); // true
console.log(function(){} instanceof Function); // true
// Object.prototype.toString.call()
console.log(Object.prototype.toString.call(null)); // "[object Null]"
console.log(Object.prototype.toString.call([])); // "[object Array]"
2. 什么是变量提升(Hoisting)?
答案: 变量提升是JavaScript引擎在执行代码前,将变量和函数声明提升到当前作用域顶部的过程。
详解:
// 变量提升
console.log(a); // undefined
var a = 10;
// 等价于:
var a;
console.log(a); // undefined
a = 10;
// 函数提升
foo(); // "Hello"
function foo() {
console.log("Hello");
}
// let和const不会提升
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 20;
// 函数表达式不会提升
bar(); // TypeError: bar is not a function
var bar = function() {
console.log("World");
};
实际应用:
// 避免变量提升带来的问题
function example() {
// 将所有变量声明放在函数顶部
var a, b, c;
// 业务逻辑
a = 1;
b = 2;
c = a + b;
return c;
}
// 使用let/const避免提升
function modernExample() {
const a = 1;
const b = 2;
const c = a + b;
return c;
}
3. 什么是事件循环(Event Loop)?
答案: 事件循环是JavaScript处理异步操作的机制,通过任务队列和微任务队列来管理代码执行顺序。
详解:
console.log('1'); // 同步任务
setTimeout(() => {
console.log('2'); // 宏任务
}, 0);
Promise.resolve().then(() => {
console.log('3'); // 微任务
});
console.log('4'); // 同步任务
// 输出顺序:1, 4, 3, 2
执行顺序:
- 同步任务:立即执行
- 微任务:Promise.then、process.nextTick、MutationObserver
- 宏任务:setTimeout、setInterval、setImmediate、requestAnimationFrame
实际应用:
// 异步操作示例
function asyncExample() {
console.log('开始');
// 宏任务
setTimeout(() => {
console.log('宏任务1');
// 微任务
Promise.resolve().then(() => {
console.log('微任务1');
});
}, 0);
// 微任务
Promise.resolve().then(() => {
console.log('微任务2');
// 宏任务
setTimeout(() => {
console.log('宏任务2');
}, 0);
});
console.log('结束');
}
// 输出:开始, 结束, 微任务2, 宏任务1, 微任务1, 宏任务2
🔒 作用域与闭包篇
4. 什么是闭包(Closure)?
答案: 闭包是指有权访问另一个函数作用域中变量的函数,即使外部函数已经执行完毕。
详解:
function outer() {
let count = 0;
function inner() {
count++;
console.log(count);
}
return inner;
}
const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3
闭包的应用场景:
// 1. 数据私有化
function createCounter() {
let count = 0;
return {
increment() {
count++;
return count;
},
decrement() {
count--;
return count;
},
getCount() {
return count;
}
};
}
const counter = createCounter();
console.log(counter.getCount()); // 0
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.decrement()); // 1
// 2. 函数工厂
function multiply(x) {
return function(y) {
return x * y;
};
}
const multiplyBy2 = multiply(2);
const multiplyBy3 = multiply(3);
console.log(multiplyBy2(4)); // 8
console.log(multiplyBy3(4)); // 12
// 3. 事件处理
function createButtonHandler(id) {
return function() {
console.log(`Button ${id} clicked`);
};
}
const button1Handler = createButtonHandler(1);
const button2Handler = createButtonHandler(2);
5. 什么是作用域链(Scope Chain)?
答案: 作用域链是JavaScript引擎查找变量时遵循的规则,从当前作用域开始,逐级向上查找。
详解:
let globalVar = 'global';
function outer() {
let outerVar = 'outer';
function inner() {
let innerVar = 'inner';
console.log(innerVar); // 'inner' - 当前作用域
console.log(outerVar); // 'outer' - 外层作用域
console.log(globalVar); // 'global' - 全局作用域
}
inner();
}
outer();
作用域链查找过程:
// 变量查找示例
let x = 1;
function a() {
let x = 2;
function b() {
let x = 3;
function c() {
console.log(x); // 3 - 找到最近的x
}
c();
}
b();
}
a(); // 输出:3
6. 什么是this关键字?
答案:
this是JavaScript中的一个关键字,指向当前执行上下文的对象。
详解:
// 1. 全局上下文
console.log(this); // Window对象(浏览器)或global对象(Node.js)
// 2. 函数上下文
function normalFunction() {
console.log(this);
}
normalFunction(); // Window对象(非严格模式)或undefined(严格模式)
// 3. 对象方法
const obj = {
name: 'John',
sayHello() {
console.log(`Hello, ${this.name}`);
}
};
obj.sayHello(); // "Hello, John"
// 4. 构造函数
function Person(name) {
this.name = name;
}
const person = new Person('Alice');
console.log(person.name); // "Alice"
// 5. 箭头函数
const arrowObj = {
name: 'Bob',
sayHello: () => {
console.log(`Hello, ${this.name}`);
}
};
arrowObj.sayHello(); // "Hello, undefined" - 箭头函数没有自己的this
this绑定方式:
// 1. 默认绑定
function defaultBinding() {
console.log(this);
}
defaultBinding(); // Window对象
// 2. 隐式绑定
const obj = {
name: 'John',
method() {
console.log(this.name);
}
};
obj.method(); // "John"
// 3. 显式绑定
function explicitBinding() {
console.log(this.name);
}
const person = { name: 'Alice' };
explicitBinding.call(person); // "Alice"
explicitBinding.apply(person); // "Alice"
explicitBinding.bind(person)(); // "Alice"
// 4. new绑定
function NewBinding(name) {
this.name = name;
}
const newObj = new NewBinding('Bob');
console.log(newObj.name); // "Bob"
🔗 原型与继承篇
7. 什么是原型链(Prototype Chain)?
答案:
原型链是JavaScript实现继承的机制,通过__proto__属性连接对象和其原型对象。
详解:
// 原型链示例
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, I'm ${this.name}`);
};
const person = new Person('John');
person.sayHello(); // "Hello, I'm John"
// 原型链查找过程
console.log(person.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true
原型链查找:
// 属性查找过程
const obj = {};
// 1. 查找obj自身属性
console.log(obj.hasOwnProperty('toString')); // false
// 2. 查找obj.__proto__(Object.prototype)
console.log(obj.__proto__.hasOwnProperty('toString')); // true
// 3. 最终找到toString方法
console.log(obj.toString()); // "[object Object]"
8. 如何实现继承?
答案: JavaScript有多种继承方式:原型链继承、构造函数继承、组合继承、寄生组合继承等。
详解:
// 1. 原型链继承
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound`);
};
function Dog(name) {
this.name = name;
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
const dog = new Dog('Buddy');
dog.speak(); // "Buddy makes a sound"
// 2. 构造函数继承
function Animal(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
function Dog(name) {
Animal.call(this, name);
}
const dog1 = new Dog('Buddy');
const dog2 = new Dog('Max');
dog1.colors.push('yellow');
console.log(dog1.colors); // ['red', 'blue', 'green', 'yellow']
console.log(dog2.colors); // ['red', 'blue', 'green']
// 3. 组合继承
function Animal(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound`);
};
function Dog(name) {
Animal.call(this, name); // 继承属性
}
Dog.prototype = new Animal(); // 继承方法
Dog.prototype.constructor = Dog;
const dog = new Dog('Buddy');
dog.speak(); // "Buddy makes a sound"
// 4. 寄生组合继承(推荐)
function inheritPrototype(subType, superType) {
const prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound`);
};
function Dog(name) {
Animal.call(this, name);
}
inheritPrototype(Dog, Animal);
const dog = new Dog('Buddy');
dog.speak(); // "Buddy makes a sound"
9. ES6的class语法如何工作?
答案: ES6的class是语法糖,底层仍然基于原型链实现。
详解:
// ES6 class语法
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound`);
}
static create(name) {
return new Animal(name);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
speak() {
console.log(`${this.name} barks`);
}
}
const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak(); // "Buddy barks"
// 等价的原型链写法
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound`);
};
Animal.create = function(name) {
return new Animal(name);
};
function Dog(name, breed) {
Animal.call(this, name);
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.speak = function() {
console.log(`${this.name} barks`);
};
⚡ 异步编程篇
10. 什么是Promise?
答案: Promise是JavaScript中处理异步操作的对象,代表一个可能还没有完成的操作的最终结果。
详解:
// Promise基本用法
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
const random = Math.random();
if (random > 0.5) {
resolve('成功');
} else {
reject('失败');
}
}, 1000);
});
promise
.then(result => {
console.log('成功:', result);
})
.catch(error => {
console.log('失败:', error);
})
.finally(() => {
console.log('完成');
});
Promise链式调用:
// 链式调用
function fetchUser(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ id, name: 'John' });
}, 1000);
});
}
function fetchUserPosts(userId) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([{ id: 1, title: 'Post 1' }, { id: 2, title: 'Post 2' }]);
}, 1000);
});
}
fetchUser(1)
.then(user => {
console.log('用户信息:', user);
return fetchUserPosts(user.id);
})
.then(posts => {
console.log('用户文章:', posts);
})
.catch(error => {
console.log('错误:', error);
});
Promise静态方法:
// Promise.all - 所有Promise都成功
const promises = [
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
];
Promise.all(promises)
.then(results => {
console.log(results); // [1, 2, 3]
});
// Promise.race - 第一个完成的Promise
Promise.race([
new Promise(resolve => setTimeout(() => resolve('A'), 1000)),
new Promise(resolve => setTimeout(() => resolve('B'), 500))
])
.then(result => {
console.log(result); // "B"
});
// Promise.allSettled - 所有Promise都完成(无论成功失败)
Promise.allSettled([
Promise.resolve(1),
Promise.reject('error'),
Promise.resolve(3)
])
.then(results => {
console.log(results);
// [
// { status: 'fulfilled', value: 1 },
// { status: 'rejected', reason: 'error' },
// { status: 'fulfilled', value: 3 }
// ]
});
11. 什么是async/await?
答案: async/await是ES2017引入的语法糖,让异步代码看起来像同步代码。
详解:
// async/await基本用法
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error('获取数据失败:', error);
}
}
// 等价于Promise写法
function fetchDataPromise() {
return fetch('https://api.example.com/data')
.then(response => response.json())
.catch(error => {
console.error('获取数据失败:', error);
});
}
async/await错误处理:
// 错误处理方式
async function handleErrors() {
try {
const result = await riskyOperation();
return result;
} catch (error) {
console.error('操作失败:', error);
return null;
}
}
// 或者使用.catch()
async function handleErrors2() {
const result = await riskyOperation().catch(error => {
console.error('操作失败:', error);
return null;
});
return result;
}
并行执行:
// 串行执行
async function sequential() {
const result1 = await fetch('https://api1.com');
const result2 = await fetch('https://api2.com');
return [result1, result2];
}
// 并行执行
async function parallel() {
const [result1, result2] = await Promise.all([
fetch('https://api1.com'),
fetch('https://api2.com')
]);
return [result1, result2];
}
🆕 ES6+新特性篇
12. 什么是箭头函数?
答案: 箭头函数是ES6引入的简洁函数语法,没有自己的this、arguments、super、new.target。
详解:
// 基本语法
const add = (a, b) => a + b;
// 等价于
function add(a, b) {
return a + b;
}
// 多行函数体
const multiply = (a, b) => {
const result = a * b;
return result;
};
// 单个参数可以省略括号
const square = x => x * x;
// 无参数需要括号
const getRandom = () => Math.random();
this绑定:
// 传统函数
const obj = {
name: 'John',
traditionalMethod: function() {
setTimeout(function() {
console.log(this.name); // undefined
}, 100);
},
arrowMethod: function() {
setTimeout(() => {
console.log(this.name); // "John"
}, 100);
}
};
obj.traditionalMethod();
obj.arrowMethod();
实际应用:
// 数组方法中使用
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
const filtered = numbers.filter(n => n > 2);
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(filtered); // [3, 4, 5]
console.log(sum); // 15
13. 什么是解构赋值?
答案: 解构赋值是ES6引入的语法,可以从数组或对象中提取值并赋给变量。
详解:
// 数组解构
const [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1, 2, 3
// 跳过元素
const [first, , third] = [1, 2, 3];
console.log(first, third); // 1, 3
// 默认值
const [x = 0, y = 0] = [1];
console.log(x, y); // 1, 0
// 剩余参数
const [head, ...tail] = [1, 2, 3, 4, 5];
console.log(head); // 1
console.log(tail); // [2, 3, 4, 5]
对象解构:
// 基本对象解构
const person = { name: 'John', age: 30, city: 'New York' };
const { name, age, city } = person;
console.log(name, age, city); // "John", 30, "New York"
// 重命名
const { name: userName, age: userAge } = person;
console.log(userName, userAge); // "John", 30
// 默认值
const { name, age, country = 'USA' } = person;
console.log(country); // "USA"
// 嵌套解构
const user = {
id: 1,
profile: {
name: 'John',
email: 'john@example.com'
}
};
const { profile: { name, email } } = user;
console.log(name, email); // "John", "john@example.com"
实际应用:
// 函数参数解构
function printUser({ name, age, email = 'N/A' }) {
console.log(`Name: ${name}, Age: ${age}, Email: ${email}`);
}
printUser({ name: 'John', age: 30 }); // "Name: John, Age: 30, Email: N/A"
// 交换变量
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 2, 1
// 从函数返回多个值
function getCoordinates() {
return [10, 20];
}
const [x, y] = getCoordinates();
console.log(x, y); // 10, 20
14. 什么是模板字符串?
答案: 模板字符串是ES6引入的字符串字面量语法,支持多行字符串和字符串插值。
详解:
// 基本语法
const name = 'John';
const age = 30;
const greeting = `Hello, my name is ${name} and I'm ${age} years old.`;
console.log(greeting); // "Hello, my name is John and I'm 30 years old."
// 多行字符串
const multiLine = `
This is a
multi-line
string.
`;
console.log(multiLine);
// 表达式
const price = 10;
const quantity = 3;
const total = `Total: $${price * quantity}`;
console.log(total); // "Total: $30"
标签模板:
// 标签模板函数
function highlight(strings, ...values) {
let result = '';
strings.forEach((string, i) => {
result += string;
if (values[i]) {
result += `<span class="highlight">${values[i]}</span>`;
}
});
return result;
}
const name = 'John';
const age = 30;
const highlighted = highlight`Hello, my name is ${name} and I'm ${age} years old.`;
console.log(highlighted);
// "Hello, my name is <span class="highlight">John</span> and I'm <span class="highlight">30</span> years old."
15. 什么是let和const?
答案: let和const是ES6引入的块级作用域变量声明,let允许重新赋值,const不允许。
详解:
// let - 可以重新赋值
let count = 0;
count = 1; // 允许
// const - 不能重新赋值
const PI = 3.14159;
// PI = 3.14; // TypeError: Assignment to constant variable
// 块级作用域
{
let blockVar = 'block scope';
const blockConst = 'block constant';
}
// console.log(blockVar); // ReferenceError
// console.log(blockConst); // ReferenceError
// 暂时性死区
console.log(hoistedVar); // undefined
var hoistedVar = 'hoisted';
// console.log(tdzVar); // ReferenceError
let tdzVar = 'tdz';
const的特殊性:
// const只保证引用不变,不保证对象内容不变
const user = { name: 'John', age: 30 };
user.age = 31; // 允许
user.name = 'Jane'; // 允许
// user = { name: 'Bob' }; // TypeError
// 冻结对象
const frozenUser = Object.freeze({ name: 'John', age: 30 });
// frozenUser.age = 31; // 在严格模式下会报错
📦 模块化篇
16. ES6模块系统如何工作?
答案: ES6模块系统提供了静态的模块结构,支持导入和导出语法。
详解:
// 导出语法
// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;
// 默认导出
export default function divide(a, b) {
return a / b;
}
// 导入语法
// main.js
import { add, subtract } from './math.js';
import divide from './math.js'; // 默认导入
import * as MathUtils from './math.js'; // 命名空间导入
console.log(add(5, 3)); // 8
console.log(divide(10, 2)); // 5
console.log(MathUtils.multiply(4, 5)); // 20
动态导入:
// 动态导入
async function loadModule() {
try {
const module = await import('./math.js');
console.log(module.add(2, 3)); // 5
} catch (error) {
console.error('模块加载失败:', error);
}
}
// 条件导入
if (condition) {
import('./feature.js').then(module => {
module.default();
});
}
模块特性:
// 1. 严格模式
// 所有模块都在严格模式下运行
// 2. 静态结构
// 导入导出必须在顶层,不能在条件语句中
// 3. 单例模式
// 模块只加载一次,多次导入返回同一个实例
// 4. 循环依赖处理
// a.js
import { b } from './b.js';
export const a = 'a';
// b.js
import { a } from './a.js';
export const b = 'b';
⚡ 性能优化篇
17. 如何优化JavaScript性能?
答案: 通过减少DOM操作、使用事件委托、避免内存泄漏、代码分割等方法优化性能。
详解:
// 1. 减少DOM操作
// 不好的做法
for (let i = 0; i < 1000; i++) {
const div = document.createElement('div');
document.body.appendChild(div);
}
// 好的做法
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
const div = document.createElement('div');
fragment.appendChild(div);
}
document.body.appendChild(fragment);
// 2. 事件委托
// 不好的做法
const buttons = document.querySelectorAll('button');
buttons.forEach(button => {
button.addEventListener('click', handleClick);
});
// 好的做法
document.addEventListener('click', (event) => {
if (event.target.matches('button')) {
handleClick(event);
}
});
// 3. 防抖和节流
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// 使用示例
const debouncedSearch = debounce(searchAPI, 300);
const throttledScroll = throttle(handleScroll, 100);
内存管理:
// 避免内存泄漏
class EventHandler {
constructor() {
this.element = document.getElementById('myElement');
this.handleClick = this.handleClick.bind(this);
this.element.addEventListener('click', this.handleClick);
}
handleClick() {
console.log('Clicked');
}
destroy() {
this.element.removeEventListener('click', this.handleClick);
this.element = null;
}
}
// 使用WeakMap避免循环引用
const cache = new WeakMap();
function expensiveOperation(obj) {
if (cache.has(obj)) {
return cache.get(obj);
}
const result = /* 复杂计算 */;
cache.set(obj, result);
return result;
}
🎯 实战应用篇
18. 如何实现一个简单的状态管理?
答案: 使用发布订阅模式实现简单的状态管理。
详解:
class SimpleStore {
constructor(initialState = {}) {
this.state = initialState;
this.listeners = [];
}
getState() {
return this.state;
}
setState(newState) {
this.state = { ...this.state, ...newState };
this.notify();
}
subscribe(listener) {
this.listeners.push(listener);
return () => {
this.listeners = this.listeners.filter(l => l !== listener);
};
}
notify() {
this.listeners.forEach(listener => listener(this.state));
}
}
// 使用示例
const store = new SimpleStore({ count: 0, user: null });
// 订阅状态变化
const unsubscribe = store.subscribe((state) => {
console.log('状态更新:', state);
});
// 更新状态
store.setState({ count: 1 });
store.setState({ user: { name: 'John' } });
// 取消订阅
unsubscribe();
19. 如何实现深拷贝?
答案: 使用递归、JSON方法或第三方库实现深拷贝。
详解:
// 1. JSON方法(简单但有限制)
function deepCloneJSON(obj) {
return JSON.parse(JSON.stringify(obj));
}
// 限制:不能处理函数、undefined、Symbol、循环引用
// 2. 递归实现
function deepClone(obj, hash = new WeakMap()) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (obj instanceof Date) {
return new Date(obj.getTime());
}
if (obj instanceof RegExp) {
return new RegExp(obj);
}
if (hash.has(obj)) {
return hash.get(obj);
}
const clone = Array.isArray(obj) ? [] : {};
hash.set(obj, clone);
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key], hash);
}
}
return clone;
}
// 使用示例
const original = {
name: 'John',
age: 30,
hobbies: ['reading', 'gaming'],
address: {
city: 'New York',
country: 'USA'
},
birthday: new Date('1990-01-01'),
regex: /test/g
};
const cloned = deepClone(original);
console.log(cloned);
20. 如何实现防抖和节流?
答案: 防抖是延迟执行,节流是限制执行频率。
详解:
// 防抖 - 延迟执行
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
// 节流 - 限制频率
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => {
inThrottle = false;
}, limit);
}
};
}
// 使用示例
const debouncedSearch = debounce((query) => {
console.log('搜索:', query);
}, 300);
const throttledScroll = throttle(() => {
console.log('滚动事件');
}, 100);
// 输入框搜索
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', (e) => {
debouncedSearch(e.target.value);
});
// 滚动事件
window.addEventListener('scroll', throttledScroll);
📝 总结
本文整理了50道JavaScript核心概念和ES6+新特性的高频面试题,涵盖了:
✅ 基础知识:数据类型、变量提升、事件循环等 ✅ 核心概念:作用域、闭包、原型链、this等 ✅ 异步编程:Promise、async/await等 ✅ ES6+特性:箭头函数、解构赋值、模板字符串等 ✅ 模块化:ES6模块系统 ✅ 性能优化:DOM操作、内存管理、防抖节流等 ✅ 实战应用:状态管理、深拷贝、工具函数等
面试建议:
- 理解原理:深入理解JavaScript的运行机制
- 实践练习:多动手实现各种功能
- 关注新特性:了解ES6+的新特性和使用场景
- 性能意识:在开发中始终考虑性能问题
学习资源:
希望这些面试题能帮助你在前端面试中取得好成绩!🚀
💡 小贴士:面试时不仅要回答正确,更要展示你的思考过程和实践经验。多准备一些实际项目的例子,这样会让你的回答更有说服力!
标签: #前端面试 #JavaScript #ES6 #面试题 #前端开发 #Web开发