2025年 JavaScript 面试题的130道题目及其答案解析,万字长文,持续更新....

1. 什么是闭包(Closure)?

答案
闭包是一个函数与其词法环境的组合。换句话说,闭包可以让一个函数访问并操作其外部函数的变量,即使外部函数已经返回。

解析
当函数被创建时,它会记住其作用域(即变量的上下文),即使外部函数已经执行完毕,闭包仍然可以访问这些变量。

function outerFunction() {
    let outerVariable = 'Hello';
    return function innerFunction() {
        console.log(outerVariable);
    };
}

const inner = outerFunction();
inner(); // 输出 'Hello'

2. this 关键字的含义是什么?

答案
this 关键字指向当前执行上下文中的对象。在不同的情况下,this 的值是不同的。

解析

  • 在全局作用域中,this 指向全局对象(在浏览器中是 window)。
  • 在对象的方法中,this 指向调用该方法的对象。
  • 在构造函数中,this 指向新创建的对象。
  • 在事件处理函数中,this 通常指向触发事件的元素。

3. 什么是原型(Prototype)?

答案
原型是 JavaScript 中对象的一个重要概念,每个对象都有一个内部链接到另一个对象的属性,称为原型。

解析
对象可以通过其原型链继承属性和方法。通过修改原型,可以给所有实例添加方法和属性。

function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    console.log(`Hello, my name is ${this.name}`);
};

const alice = new Person('Alice');
alice.sayHello(); // 输出 'Hello, my name is Alice'

4. 解释事件冒泡和事件捕获的区别。

答案
事件冒泡和事件捕获是两种事件传播机制。

解析

  • 事件冒泡:事件从目标元素向上冒泡到其父元素,直到到达 document 对象。
  • 事件捕获:事件从 document 对象向下传播到目标元素。

可以通过 addEventListener 方法的第三个参数来控制是捕获还是冒泡,默认为 false(冒泡)。

element.addEventListener('click', function(event) {
    // 处理点击事件
}, false); // 冒泡

5. 什么是 Promise?

答案
Promise 是一个表示异步操作的对象,可能在未来的某个时间点完成并返回结果。

解析
Promise 有三种状态:Pending(进行中)、Fulfilled(已完成)和 Rejected(已拒绝)。使用 then 方法可以处理成功的结果,使用 catch 方法处理错误。

const myPromise = new Promise((resolve, reject) => {
    // 异步操作
    setTimeout(() => {
        resolve('成功');
    }, 1000);
});

myPromise.then(result => {
    console.log(result); // 输出 '成功'
}).catch(error => {
    console.log(error);
});

6. 什么是异步编程,如何在 JavaScript 中实现?

答案
异步编程允许程序在等待某些操作完成时继续执行其他操作,以提高效率。

解析
在 JavaScript 中,异步编程可以通过回调函数、Promises 和 async/await 实现。

// 使用 async/await
async function fetchData() {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
}
fetchData();

7. 解释 letconst 的作用域及用法。

答案
letconst 是 ES6 引入的变量声明方式,具有块级作用域。

解析

  • let:可以声明可变的变量,允许在块内重新赋值。
  • const:声明不可变的常量,必须在声明时初始化,且不可重新赋值。
if (true) {
    let x = 10;
    const y = 20;
    console.log(x, y); // 输出 10 20
}
// console.log(x); // ReferenceError: x is not defined
// console.log(y); // ReferenceError: y is not defined

8. 什么是防抖(Debouncing)和节流(Throttling)?

答案
防抖和节流都是控制函数执行频率的技术。

解析

  • 防抖:在事件触发后,延迟一段时间再执行函数,如果在延迟时间内再次触发事件,则重新计时。
  • 节流:限制函数在一定时间内只能执行一次,忽略在这段时间内的其他调用。
// 防抖实现
function debounce(func, delay) {
    let timer;
    return function(...args) {
        clearTimeout(timer);
        timer = setTimeout(() => func.apply(this, args), delay);
    };
}

// 节流实现
function throttle(func, limit) {
    let lastFunc;
    let lastRan;
    return function(...args) {
        if (!lastRan) {
            func.apply(this, args);
            lastRan = Date.now();
        } else {
            clearTimeout(lastFunc);
            lastFunc = setTimeout(() => {
                if (Date.now() - lastRan >= limit) {
                    func.apply(this, args);
                    lastRan = Date.now();
                }
            }, limit - (Date.now() - lastRan));
        }
    };
}

9. 解释 JavaScript 中的 mapfilterreduce 方法。

答案
mapfilterreduce 是数组的高阶函数,用于处理数组数据。

解析

  • map:创建一个新数组,包含调用函数处理后的每个元素。
  • filter:创建一个新数组,包含所有通过测试的元素。
  • reduce:对数组中的每个元素执行一个函数,最终计算出一个值。
const numbers = [1, 2, 3, 4, 5];

// map
const doubled = numbers.map(num => num * 2); // [2, 4, 6, 8, 10]

// filter
const evens = numbers.filter(num => num % 2 === 0); // [2, 4]

// reduce
const sum = numbers.reduce((acc, num) => acc + num, 0); // 15

10. 什么是 JavaScript 中的 async/await

答案
async/await 是用于处理异步编程的语法糖,使得异步代码更易读。

解析
async 用于定义一个异步函数,await 用于等待一个 Promise 的解析。

async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Error:', error);
    }
}
fetchData();

11. 什么是 localStoragesessionStorage

答案
localStoragesessionStorage 是 Web Storage API 的一部分,用于在用户的浏览器中存储数据。

解析

  • localStorage:用于永久存储数据,除非手动删除,否则数据会一直保留在浏览器中。
  • sessionStorage:用于在一个会话中存储数据,数据在浏览器标签页关闭后会被清除。
// 使用 localStorage
localStorage.setItem('key', 'value');
console.log(localStorage.getItem('key')); // 输出 'value'

// 使用 sessionStorage
sessionStorage.setItem('sessionKey', 'sessionValue');
console.log(sessionStorage.getItem('sessionKey')); // 输出 'sessionValue'

12. nullundefined 的区别是什么?

答案
nullundefined 都表示“无”或“没有值”,但它们在 JavaScript 中是不同的类型。

解析

  • undefined:表示变量被声明但未赋值,或对象属性不存在。
  • null:表示一个无值的对象,通常用于指示变量应有的值为空。
let a;
console.log(a); // 输出 undefined

let b = null;
console.log(b); // 输出 null

13. 解释 JavaScript 中的防止重复提交的逻辑。

答案
防止重复提交通常通过禁用按钮或使用标志变量来实现。

解析
可以在表单提交时禁用提交按钮,避免用户多次点击。

document.getElementById('submitBtn').addEventListener('click', function() {
    this.disabled = true; // 禁用按钮
    // 处理表单提交逻辑
});

14. 什么是事件委托(Event Delegation)?

答案
事件委托是一种事件处理模式,将事件处理程序附加到父元素,而不是直接附加到每个子元素上。

解析
当子元素触发事件时,事件会冒泡到父元素,父元素的事件处理程序可以处理这些事件。这种方式可以提高性能,尤其是在动态添加子元素的情况下。

document.getElementById('parent').addEventListener('click', function(event) {
    if (event.target.matches('.child')) {
        console.log('Child element clicked:', event.target);
    }
});

15. 如何处理 JavaScript 中的异步错误?

答案
在 JavaScript 中,异步函数的错误可以通过 try/catch 语句或 .catch() 方法来处理。

解析

  • 使用 async/await 时,可以在 try/catch 块中捕获错误。
  • 使用 Promise 时,可以链式调用 .catch() 方法处理错误。
// 使用 async/await
async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Error:', error);
    }
}

// 使用 Promise
fetch('https://api.example.com/data')
    .then(response => response.json())
    .catch(error => console.error('Error:', error));

16. 解释 JavaScript 中的模块化。

答案
模块化是将代码分割成独立的模块,每个模块拥有自己的作用域,可以更好地管理代码的组织和依赖关系。

解析
在 JavaScript 中,可以使用 ES6 模块(importexport)或 CommonJS(requiremodule.exports)进行模块化。

// ES6 模块
// module.js
export const myFunction = () => { console.log('Hello'); };

// main.js
import { myFunction } from './module.js';
myFunction(); // 输出 'Hello'

17. 解释 JavaScript 中的深拷贝和浅拷贝。

答案
浅拷贝和深拷贝是复制对象的两种方式。

解析

  • 浅拷贝:只复制对象的引用,对于嵌套对象,引用仍指向原对象。
  • 深拷贝:递归复制对象,确保嵌套对象也是新的实例。
// 浅拷贝
const obj1 = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, obj1);
shallowCopy.b.c = 3; // 修改嵌套对象
console.log(obj1.b.c); // 输出 3,原对象也受到影响

// 深拷贝
const deepCopy = JSON.parse(JSON.stringify(obj1));
deepCopy.b.c = 4; // 修改嵌套对象
console.log(obj1.b.c); // 输出 3,原对象不受影响

18. 解释 setTimeoutsetInterval 的区别。

答案
setTimeoutsetInterval 都用于定时执行代码,但有明显的区别。

解析

  • setTimeout:在指定的延迟后执行一次代码。
  • setInterval:按照指定的时间间隔重复执行代码。
setTimeout(() => {
    console.log('Executed after 1 second');
}, 1000); // 1秒后执行

const intervalId = setInterval(() => {
    console.log('Executed every 1 second');
}, 1000); // 每1秒执行

// 使用 clearInterval 取消
// clearInterval(intervalId);

19. 如何在 JavaScript 中实现懒加载(Lazy Loading)?

答案
懒加载是一种优化技术,推迟加载不必要的内容,直到需要时才加载。

解析
可以使用 Intersection Observer API 来实现懒加载,或者在滚动事件中手动检查元素是否可见。

// 使用 Intersection Observer 实现懒加载
const images = document.querySelectorAll('img[data-src]');
const options = {
    root: null,
    threshold: 0.1
};

const callback = (entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src; // 加载图片
            observer.unobserve(img); // 停止观察
        }
    });
};

const observer = new IntersectionObserver(callback, options);
images.forEach(image => {
    observer.observe(image);
});

20. 解释 JavaScript 中的 bindcallapply 方法。

答案
bindcallapply 是函数对象的方法,用于改变函数的 this 指向。

解析

  • call:立即调用函数,并指定 this 的值,后面可以传入参数。
  • apply:与 call 类似,但参数以数组的形式传递。
  • bind:返回一个新的函数,this 被永久绑定到指定对象,并可以传入参数。
function greet(greeting) {
    console.log(`${greeting}, ${this.name}`);
}

const person = { name: 'Alice' };

greet.call(person, 'Hello'); // 输出 'Hello, Alice'
greet.apply(person, ['Hi']); // 输出 'Hi, Alice'

const greetAlice = greet.bind(person);
greetAlice('Hey'); // 输出 'Hey, Alice'

21. 什么是箭头函数(Arrow Function)?

答案
箭头函数是 ES6 引入的一种简洁的函数表达式语法。

解析
箭头函数没有自己的 this 值,它会捕获外部上下文的 this 值。箭头函数的语法更加简洁,尤其是在定义匿名函数时。

const add = (a, b) => a + b;
console.log(add(2, 3)); // 输出 5

const obj = {
    value: 42,
    getValue: function() {
        return () => this.value; // 注意这里的 this
    }
};

const getValue = obj.getValue();
console.log(getValue()); // 输出 42

22. 解释 JavaScript 中的 Promise.all() 方法。

答案
Promise.all() 是一个静态方法,用于将多个 Promise 实例包装成一个新的 Promise。

解析
当所有的 Promise 都成功时,返回的 Promise 解析为一个数组,包含每个 Promise 的结果;如果有一个 Promise 失败,返回的 Promise 将被拒绝。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(values => {
    console.log(values); // 输出 [3, 42, 'foo']
}).catch(error => {
    console.error('Error:', error);
});

23. 什么是 async 函数?

答案
async 函数是 ES2017 引入的一种函数声明方式,返回一个 Promise。

解析
async 函数内部,可以使用 await 关键字来等待 Promise 的解析。async 函数会隐式地将返回值包装为 Promise。

async function fetchData() {
    return 'Data fetched'; // 这会被包装成 Promise
}

fetchData().then(data => console.log(data)); // 输出 'Data fetched'

24. 解释 JavaScript 中的深拷贝和浅拷贝的区别以及应用场景。

答案
深拷贝和浅拷贝用于复制对象,但它们的工作方式不同。

解析

  • 浅拷贝:只复制对象的引用,对于嵌套对象,仍然指向原对象。例如,使用 Object.assign()
  • 深拷贝:递归复制对象,确保嵌套对象也是新的实例。例如,使用 JSON.parse(JSON.stringify(obj)) 或者使用 Lodash 的 _.cloneDeep()

应用场景

  • 使用浅拷贝时,适合处理简单对象。
  • 使用深拷贝时,适合处理复杂对象,确保不会影响原对象。

25. 如何处理 JavaScript 中的内存泄漏?

答案
内存泄漏是指程序中不再使用的对象仍被引用,导致无法被垃圾回收器回收。

解析
常见的内存泄漏情况包括:

  • 全局变量的使用。
  • 事件监听器未被移除。
  • 闭包持有不必要的引用。

处理方式

  • 确保及时移除事件监听器。
  • 使用 WeakMap 或 WeakSet 来存储对象引用。
  • 定期检查和清理不再使用的对象。

26. 解释 JavaScript 中的 setImmediateprocess.nextTick

答案
setImmediateprocess.nextTick 是 Node.js 中用于调度异步操作的方法。

解析

  • process.nextTick:将回调函数添加到当前操作的末尾,优先于 I/O 操作。
  • setImmediate:将回调函数添加到下一个事件循环的队列中,在 I/O 操作之后执行。
console.log('Start');

process.nextTick(() => {
    console.log('Next Tick');
});

setImmediate(() => {
    console.log('Immediate');
});

console.log('End');
// 输出顺序:Start -> End -> Next Tick -> Immediate

27. 解释 JavaScript 中的 Symbol 类型。

答案
Symbol 是 ES6 引入的一种新的原始数据类型,表示唯一且不可变的值。

解析
Symbol 通常用于为对象的属性创建唯一标识符,避免属性冲突。

const sym1 = Symbol('description');
const sym2 = Symbol('description');

console.log(sym1 === sym2); // 输出 false

const obj = {
    [sym1]: 'value1'
};

console.log(obj[sym1]); // 输出 'value1'

28. 什么是 class 关键字,如何使用它?

答案
class 关键字是 ES6 引入的用于定义类的语法。

解析
类是构造函数的语法糖,可以使用 constructor 方法定义构造函数,使用 extends 关键字进行继承。

class Person {
    constructor(name) {
        this.name = name;
    }

    greet() {
        console.log(`Hello, my name is ${this.name}`);
    }
}

const alice = new Person('Alice');
alice.greet(); // 输出 'Hello, my name is Alice'

29. 解释 JavaScript 中的自执行函数(IIFE)。

答案
自执行函数(Immediately Invoked Function Expression, IIFE)是一种在定义时立即执行的函数。

解析
IIFE 通常用于创建一个新的作用域,避免变量污染全局作用域。

(function() {
    const message = 'Hello, World!';
    console.log(message);
})(); // 输出 'Hello, World!'

// console.log(message); // ReferenceError: message is not defined

30. 如何在 JavaScript 中实现函数节流(Throttling)?

答案
函数节流是一种控制函数执行频率的技术,确保函数在一定时间内只被执行一次。

解析
可以使用时间戳或定时器来实现节流。

function throttle(func, limit) {
    let lastFunc;
    let lastRan;

    return function(...args) {
        if (!lastRan) {
            func.apply(this, args);
            lastRan = Date.now();
        } else {
            clearTimeout(lastFunc);
            lastFunc = setTimeout(() => {
                if (Date.now() - lastRan >= limit) {
                    func.apply(this, args);
                    lastRan = Date.now();
                }
            }, limit - (Date.now() - lastRan));
        }
    };
}

// 用法示例
window.addEventListener('resize', throttle(() => {
    console.log('Resize event');
}, 1000));

31. 解释 JavaScript 中的 WeakMapWeakSet

答案
WeakMapWeakSet 是 ES6 引入的集合类型,分别用于存储对象的键值对和唯一对象。

解析

  • WeakMap:类似于 Map,但其键必须是对象,并且不会阻止垃圾回收。如果没有其他引用,WeakMap 中的键值对可以被垃圾回收。
  • WeakSet:类似于 Set,但只能存储对象,并且同样不会阻止垃圾回收。
let obj = {};
const weakMap = new WeakMap();
weakMap.set(obj, 'value');

console.log(weakMap.get(obj)); // 输出 'value'

obj = null; // 现在 obj 可以被垃圾回收

32. 如何在 JavaScript 中实现深度克隆(Deep Clone)?

答案
深度克隆是指复制一个对象及其嵌套对象的所有值,而不是仅复制引用。

解析
可以使用 JSON.parse(JSON.stringify(obj)) 实现深度克隆,但这种方法有局限性(如无法处理函数、日期、正则表达式等)。更通用的方法是使用递归。

function deepClone(obj) {
    if (obj === null || typeof obj !== 'object') {
        return obj; // 基本类型直接返回
    }

    const clone = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            clone[key] = deepClone(obj[key]); // 递归复制
        }
    }
    return clone;
}

const original = { a: 1, b: { c: 2 } };
const copied = deepClone(original);
console.log(copied); // 输出 { a: 1, b: { c: 2 } }

33. 什么是 JavaScript 中的模块化?如何使用 ES6 模块?

答案
模块化是将代码分割成小的、可重用的代码单元(模块),每个模块可以独立开发、测试和维护。

解析
ES6 引入了模块化语法,通过 importexport 关键字实现模块的导入与导出。

// 在 module.js 中
export const message = 'Hello, World!';
export function greet() {
    console.log(message);
}

// 在 main.js 中
import { message, greet } from './module.js';
console.log(message); // 输出 'Hello, World!'
greet(); // 输出 'Hello, World!'

34. 解释 JavaScript 中的 Object.freeze() 方法。

答案
Object.freeze() 方法用于冻结一个对象,使其无法被修改。

解析
冻结后,该对象的属性不能被添加、删除或修改,也不能改变其可枚举性和可配置性。

const obj = { name: 'Alice' };
Object.freeze(obj);

obj.name = 'Bob'; // 不会生效
console.log(obj.name); // 输出 'Alice'

obj.age = 25; // 不会生效
console.log(obj.age); // 输出 undefined

35. 如何在 JavaScript 中实现事件的解绑?

答案
解绑事件通常通过 removeEventListener 方法实现。

解析
需要确保传递给 removeEventListener 的函数引用与添加事件监听器时的函数相同。

function handleClick() {
    console.log('Clicked!');
}

document.getElementById('myButton').addEventListener('click', handleClick);

// 解绑事件
document.getElementById('myButton').removeEventListener('click', handleClick);

36. 解释 JavaScript 中的 Promise.race() 方法。

答案
Promise.race() 是一个静态方法,返回一个 Promise,该 Promise 解析或拒绝为第一个完成的 Promise 的结果。

解析
如果传入的 Promise 数组中任一 Promise 解析,则 Promise.race() 立即返回该 Promise 的结果。

const promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'First');
});
const promise2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 200, 'Second');
});

Promise.race([promise1, promise2]).then(result => {
    console.log(result); // 输出 'First'
});

37. 什么是 Array.prototype.reduce() 方法?

答案
Array.prototype.reduce() 方法用于将数组中的所有元素归纳为一个单一的值。

解析
reduce() 方法接受一个回调函数和一个初始值。回调函数接收四个参数:累加器、当前值、当前索引和数组本身。

const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 输出 10

38. 解释 JavaScript 中的 for...of 循环。

答案
for...of 循环用于遍历可迭代对象(如数组、字符串、Map、Set 等)。

解析
for...in 循环不同,for...of 循环遍历的是对象的值,而不是属性名。

const array = [1, 2, 3];
for (const value of array) {
    console.log(value); // 输出 1, 2, 3
}

const str = 'hello';
for (const char of str) {
    console.log(char); // 输出 'h', 'e', 'l', 'l', 'o'
}

39. 如何在 JavaScript 中实现一个简单的事件总线(Event Bus)?

答案
事件总线是一种发布-订阅模式的实现,允许不同组件之间进行通信。

解析
可以使用对象来存储事件及其处理函数,并提供 onemitoff 方法。

class EventBus {
    constructor() {
        this.events = {};
    }

    on(event, listener) {
        if (!this.events[event]) {
            this.events[event] = [];
        }
        this.events[event].push(listener);
    }

    emit(event, ...args) {
        if (this.events[event]) {
            this.events[event].forEach(listener => listener(...args));
        }
    }

    off(event, listener) {
        if (!this.events[event]) return;
        this.events[event] = this.events[event].filter(l => l !== listener);
    }
}

// 使用示例
const bus = new EventBus();
const listener = data => console.log(data);

bus.on('testEvent', listener);
bus.emit('testEvent', 'Hello, Event Bus!'); // 输出 'Hello, Event Bus!'
bus.off('testEvent', listener);

40. 什么是 fetch API,如何使用它?

答案
fetch API 是一种用于发起网络请求的现代接口,返回一个 Promise。

解析
fetch 方法可以用于发送 GET、POST 等请求,支持处理响应数据。

fetch('https://api.example.com/data')
    .then(response => {
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        return response.json();
    })
    .then(data => console.log(data))
    .catch(error => console.error('Fetch error:', error));

41. 解释 JavaScript 中的 Array.prototype.splice() 方法。

答案
Array.prototype.splice() 方法用于改变数组的内容,通过添加、删除或替换现有元素。

解析
splice 方法接受三个参数:起始索引、要删除的元素数量和要添加的元素。它会修改原数组并返回被删除的元素。

const fruits = ['Apple', 'Banana', 'Cherry'];
const removed = fruits.splice(1, 1, 'Orange', 'Mango');
console.log(fruits); // 输出 ['Apple', 'Orange', 'Mango', 'Cherry']
console.log(removed); // 输出 ['Banana']

42. 如何在 JavaScript 中实现节流(Throttling)?

答案
节流是一种控制函数执行频率的技术,确保在一定时间内只能执行一次。

解析
可以使用时间戳或定时器来实现节流。

function throttle(func, limit) {
    let lastFunc;
    let lastRan;

    return function(...args) {
        if (!lastRan) {
            func.apply(this, args);
            lastRan = Date.now();
        } else {
            clearTimeout(lastFunc);
            lastFunc = setTimeout(() => {
                if (Date.now() - lastRan >= limit) {
                    func.apply(this, args);
                    lastRan = Date.now();
                }
            }, limit - (Date.now() - lastRan));
        }
    };
}

// 用法示例
window.addEventListener('resize', throttle(() => {
    console.log('Resize event');
}, 1000));

43. 解释 JavaScript 中的 Array.prototype.filter() 方法。

答案
Array.prototype.filter() 方法用于创建一个新数组,其中包含所有通过测试的元素。

解析
该方法接受一个回调函数,回调函数对数组中的每个元素进行测试,返回 truefalse

const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // 输出 [2, 4]

44. 解释 try...catch 语句在 JavaScript 中的用法。

答案
try...catch 语句用于处理异常,可以捕获在 try 块中发生的错误。

解析
try 块中的代码会被执行,如果发生错误,则会跳转到 catch 块中进行处理。

try {
    const result = riskyFunction(); // 可能抛出错误的函数
} catch (error) {
    console.error('Error occurred:', error);
}

45. 什么是 setTimeoutsetInterval 的区别?

答案
setTimeoutsetInterval 都是用于调度延时执行代码的方法,但它们的用法不同。

解析

  • setTimeout:在指定的时间后执行一次回调函数。
  • setInterval:按照指定的时间间隔重复执行回调函数。
setTimeout(() => {
    console.log('Executed after 1 second');
}, 1000); // 1秒后执行

const intervalId = setInterval(() => {
    console.log('Executed every 1 second');
}, 1000); // 每1秒执行

// 使用 clearInterval 取消
// clearInterval(intervalId);

46. 解释 JavaScript 中的 Object.assign() 方法。

答案
Object.assign() 方法用于将一个或多个源对象的可枚举属性复制到目标对象。

解析
该方法返回目标对象,通常用于合并对象。

const target = { a: 1 };
const source = { b: 2, c: 3 };
const returnedTarget = Object.assign(target, source);

console.log(target); // 输出 { a: 1, b: 2, c: 3 }
console.log(returnedTarget); // 输出 { a: 1, b: 2, c: 3 }

47. 什么是 JavaScript 中的 Promise

答案
Promise 是表示异步操作的对象,可能在未来的某个时间点完成并返回结果。

解析
Promise 有三种状态:Pending(进行中)、Fulfilled(已完成)和 Rejected(已拒绝)。使用 then() 方法处理成功的结果,使用 catch() 方法处理错误。

const myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功');
    }, 1000);
});

myPromise.then(result => {
    console.log(result); // 输出 '成功'
}).catch(error => {
    console.log(error);
});

48. 如何在 JavaScript 中处理异步操作?

答案
在 JavaScript 中,可以使用回调函数、Promises 和 async/await 来处理异步操作。

解析

  • 回调函数:在异步操作完成时传递的函数。
  • Promises:通过 then()catch() 方法处理成功和失败的结果。
  • async/await:使用 async 函数和 await 关键字,使异步代码看起来像同步代码。
async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Error:', error);
    }
}
fetchData();

49. 解释 JavaScript 中的 Object.keys() 方法。

答案
Object.keys() 方法返回一个由给定对象的自身可枚举属性的键组成的数组。

解析
该方法只返回对象的可枚举属性,不包括原型链中的属性。

const obj = { a: 1, b: 2, c: 3 };
const keys = Object.keys(obj);
console.log(keys); // 输出 ['a', 'b', 'c']

50. 什么是 JavaScript 中的 Event Loop

答案
事件循环(Event Loop)是 JavaScript 中处理异步操作的机制,确保非阻塞代码的执行。

解析
JavaScript 是单线程的,通过事件循环来管理异步操作。调用栈、任务队列和微任务队列协同工作,确保异步代码在调用栈为空时执行。

console.log('Start');

setTimeout(() => {
    console.log('Timeout');
}, 0);

Promise.resolve().then(() => {
    console.log('Promise');
});

console.log('End');
// 输出顺序:Start -> End -> Promise -> Timeout

51. 什么是 typeof 运算符?

答案
typeof 运算符用于返回一个变量或表达式的数据类型。

解析
它会返回一个表示数据类型的字符串,包括:"undefined""object""boolean""number""string""function""symbol"

console.log(typeof 'Hello'); // 输出 'string'
console.log(typeof 42); // 输出 'number'
console.log(typeof true); // 输出 'boolean'
console.log(typeof {}; // 输出 'object'
console.log(typeof function() {}; // 输出 'function'

52. 解释 JavaScript 中的 Array.prototype.map() 方法。

答案
Array.prototype.map() 方法创建一个新数组,其中包含调用提供的函数处理过的每个元素的结果。

解析
该方法不会改变原数组,并返回一个新数组。

const numbers = [1, 2, 3, 4];
const squares = numbers.map(num => num * num);
console.log(squares); // 输出 [1, 4, 9, 16]

53. 什么是 letconst 的作用域?

答案
letconst 是 ES6 引入的块级作用域变量声明方式。

解析

  • let:声明的变量只在其块级作用域内有效,可以重新赋值。
  • const:声明的变量也只在其块级作用域内有效,但必须在声明时赋值,且不可重新赋值。
if (true) {
    let x = 10;
    const y = 20;
    console.log(x); // 输出 10
    console.log(y); // 输出 20
}
// console.log(x); // ReferenceError: x is not defined
// console.log(y); // ReferenceError: y is not defined

54. 解释什么是 JavaScript 中的闭包(Closure)。

答案
闭包是一个函数与其词法环境的组合,允许函数访问外部函数的变量,即使外部函数已经返回。

解析
闭包可以用于数据封装和私有变量。

function outerFunction() {
    let outerVariable = 'Hello';
    return function innerFunction() {
        console.log(outerVariable);
    };
}

const inner = outerFunction();
inner(); // 输出 'Hello'

55. 如何使用 localStoragesessionStorage

答案
localStoragesessionStorage 是 Web Storage API 的一部分,用于在浏览器中存储数据。

解析

  • localStorage:数据会永久保存在浏览器中,直到被手动删除。
  • sessionStorage:数据在当前会话中有效,关闭浏览器标签页后会被删除。
// localStorage 示例
localStorage.setItem('key', 'value');
console.log(localStorage.getItem('key')); // 输出 'value'

// sessionStorage 示例
sessionStorage.setItem('sessionKey', 'sessionValue');
console.log(sessionStorage.getItem('sessionKey')); // 输出 'sessionValue'

56. 解释 JavaScript 中的 Promise.allSettled() 方法。

答案
Promise.allSettled() 方法返回一个 Promise,表示所有输入的 Promise 都已完成,无论成功与否。

解析
返回的 Promise 解析为一个数组,包含每个 Promise 的结果对象,结果对象表示状态(fulfilled 或 rejected)和对应的值或原因。

const promise1 = Promise.resolve(3);
const promise2 = Promise.reject('Error');
const promise3 = Promise.resolve(5);

Promise.allSettled([promise1, promise2, promise3]).then(results => {
    console.log(results);
    // 输出:
    // [
    //   { status: 'fulfilled', value: 3 },
    //   { status: 'rejected', reason: 'Error' },
    //   { status: 'fulfilled', value: 5 }
    // ]
});

57. 什么是 DOM 事件?

答案
DOM 事件是用户与网页交互时触发的事件,如点击、输入、鼠标移动等。

解析
可以使用事件监听器(addEventListener)来处理这些事件。

document.getElementById('myButton').addEventListener('click', function() {
    console.log('Button clicked!');
});

58. 解释 JavaScript 中的解构赋值(Destructuring Assignment)。

答案
解构赋值是 ES6 引入的一个语法,用于从数组或对象中提取值并赋值给变量。

解析
对数组和对象的解构方式有所不同。

// 数组解构
const arr = [1, 2, 3];
const [first, second] = arr;
console.log(first); // 输出 1
console.log(second); // 输出 2

// 对象解构
const obj = { a: 1, b: 2 };
const { a, b } = obj;
console.log(a); // 输出 1
console.log(b); // 输出 2

59. 如何使用 JavaScript 实现深拷贝?

答案
深拷贝是复制一个对象及其嵌套对象的所有值,而不仅仅是引用。

解析
可以使用递归、JSON.parse(JSON.stringify(obj)) 或使用第三方库(如 Lodash 的 _.cloneDeep())实现深拷贝。

function deepClone(obj) {
    if (obj === null || typeof obj !== 'object') {
        return obj; // 基本类型直接返回
    }

    const clone = Array.isArray(obj) ? [] : {};
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            clone[key] = deepClone(obj[key]); // 递归复制
        }
    }
    return clone;
}

const original = { a: 1, b: { c: 2 } };
const copied = deepClone(original);
console.log(copied); // 输出 { a: 1, b: { c: 2 } }

60. 解释 JavaScript 中的 Array.prototype.reduceRight() 方法。

答案
Array.prototype.reduceRight() 方法从数组的最后一个元素开始,逐个应用回调函数,最终计算出一个单一的值。

解析
该方法接受一个回调函数和一个初始值,返回最终的计算结果。

const numbers = [1, 2, 3, 4];
const sum = numbers.reduceRight((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 输出 10

61. 解释 JavaScript 中的 class 关键字及其用法。

答案
class 关键字用于定义类,是 ES6 引入的语法,是构造函数的语法糖。

解析
类可以包含构造函数(constructor)和方法(包括实例方法和静态方法)。

class Animal {
    constructor(name) {
        this.name = name;
    }

    speak() {
        console.log(`${this.name} makes a noise.`);
    }
}

const dog = new Animal('Dog');
dog.speak(); // 输出 'Dog makes a noise.'

62. 什么是 JavaScript 中的原型链(Prototype Chain)?

答案
原型链是 JavaScript 中实现继承和共享属性的方法。

解析
每个对象都有一个内部属性指向其原型对象。通过原型链,可以访问对象的属性和方法。

function Parent() {
    this.parentProperty = 'parent';
}

Parent.prototype.getParentProperty = function() {
    return this.parentProperty;
};

function Child() {
    this.childProperty = 'child';
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

const child = new Child();
console.log(child.getParentProperty()); // 输出 'parent'

63. 解释 JavaScript 中的 bind 方法及其用法。

答案
bind 方法创建一个新的函数,在调用时将 this 关键字设置为提供的值,并可以预先设置参数。

解析
bind 返回一个新函数,原函数的 this 被永久绑定。

function greet() {
    console.log(`Hello, my name is ${this.name}`);
}

const person = { name: 'Alice' };
const greetAlice = greet.bind(person);
greetAlice(); // 输出 'Hello, my name is Alice'

64. 如何使用 Array.prototype.every() 方法?

答案
Array.prototype.every() 方法测试数组中的所有元素是否都通过指定的测试函数。

解析
如果所有元素都满足条件,返回 true;否则返回 false

const numbers = [1, 2, 3, 4];
const allPositive = numbers.every(num => num > 0);
console.log(allPositive); // 输出 true

65. 解释 JavaScript 中的 Array.prototype.find() 方法。

答案
Array.prototype.find() 方法返回数组中满足提供的测试函数的第一个元素的值。

解析
如果没有找到满足条件的元素,返回 undefined

const numbers = [5, 12, 8, 130, 44];
const found = numbers.find(num => num > 10);
console.log(found); // 输出 12

66. 什么是 JavaScript 中的 this 关键字?

答案
this 关键字指向当前执行上下文中的对象,其值取决于函数的调用方式。

解析

  • 在全局上下文中,this 指向全局对象(浏览器中的 window)。
  • 在对象的方法中,this 指向调用该方法的对象。
  • 在构造函数中,this 指向新创建的对象。
  • 在事件处理函数中,this 通常指向事件的目标元素。

67. 解释 JavaScript 中的 for...in 循环。

答案
for...in 循环用于遍历对象的可枚举属性。

解析
它会遍历对象的所有可枚举属性,包括继承的属性,但不推荐用于数组,因为顺序不一定是数字索引的顺序。

const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
    console.log(`${key}: ${obj[key]}`);
}
// 输出:
// a: 1
// b: 2
// c: 3

68. 如何在 JavaScript 中实现函数的防抖(Debouncing)?

答案
防抖是一种控制频繁事件触发的技术,确保事件在一定时间后执行,如果在这段时间内再次触发,则重新计时。

解析
可以使用 setTimeout 来实现防抖。

function debounce(func, delay) {
    let timer;
    return function(...args) {
        clearTimeout(timer);
        timer = setTimeout(() => func.apply(this, args), delay);
    };
}

// 使用示例
window.addEventListener('resize', debounce(() => {
    console.log('Resize event');
}, 1000));

69. 解释 JavaScript 中的 Array.prototype.slice() 方法。

答案
Array.prototype.slice() 方法返回一个新的数组,包含从原数组中提取的部分元素。

解析
该方法不会修改原数组,可以接受两个参数:开始索引和结束索引(不包括结束索引)。

const fruits = ['Apple', 'Banana', 'Cherry', 'Date'];
const sliced = fruits.slice(1, 3);
console.log(sliced); // 输出 ['Banana', 'Cherry']
console.log(fruits); // 原数组未被修改

70. 什么是 JavaScript 的事件冒泡和事件捕获?

答案
事件冒泡和事件捕获是 DOM 事件传播的两种机制。

解析

  • 事件冒泡:事件从目标元素开始,逐级向上传播到 document
  • 事件捕获:事件从 document 开始,逐级向下传播到目标元素。

可以通过 addEventListener 的第三个参数控制事件处理的顺序,默认为 false(冒泡)。

const parent = document.getElementById('parent');
const child = document.getElementById('child');

parent.addEventListener('click', () => {
    console.log('Parent clicked');
}, false); // 冒泡

child.addEventListener('click', () => {
    console.log('Child clicked');
}, true); // 捕获

71. 解释 JavaScript 中的 Object.create() 方法。

答案
Object.create() 方法用于创建一个新对象,指定其原型对象。

解析
该方法接受一个对象作为参数,该对象将作为新对象的原型。

const animal = {
    speak() {
        console.log('Animal speaks');
    }
};

const dog = Object.create(animal);
dog.speak(); // 输出 'Animal speaks'

72. 什么是 JavaScript 中的 Array.prototype.concat() 方法?

答案
Array.prototype.concat() 方法用于合并两个或多个数组,返回一个新数组。

解析
原数组不会被修改。

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const combined = array1.concat(array2);
console.log(combined); // 输出 [1, 2, 3, 4, 5, 6]

73. 如何在 JavaScript 中实现事件委托?

答案
事件委托是一种将事件处理器附加到父元素而不是子元素的技术。

解析
当子元素触发事件时,事件会冒泡到父元素,父元素的事件处理器可以处理这些事件。这种方式可以提高性能,特别是对于动态添加的子元素。

const parent = document.getElementById('parent');
parent.addEventListener('click', function(event) {
    if (event.target.matches('.child')) {
        console.log('Child element clicked:', event.target);
    }
});

74. 解释 JavaScript 中的 Promise 的状态。

答案
Promise 有三种状态:Pending(进行中)、Fulfilled(已完成)和 Rejected(已拒绝)。

解析

  • Pending:初始状态,表示操作尚未完成。
  • Fulfilled:表示操作成功完成,并可以获取结果。
  • Rejected:表示操作失败,并可以获取错误信息。
const myPromise = new Promise((resolve, reject) => {
    // 异步操作
    setTimeout(() => {
        const success = true;
        if (success) {
            resolve('Success!');
        } else {
            reject('Failure!');
        }
    }, 1000);
});

myPromise
    .then(result => console.log(result)) // 输出 'Success!'
    .catch(error => console.log(error));

75. 如何使用 async/await 处理异步操作?

答案
async/await 是一种更简洁的异步编程方式,使异步代码的书写方式更接近同步。

解析
async 函数返回一个 Promise,await 用于等待 Promise 解析。

async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Error:', error);
    }
}
fetchData();

76. 解释 JavaScript 中的 Array.prototype.includes() 方法。

答案
Array.prototype.includes() 方法用于判断数组是否包含某个值,返回布尔值。

解析
该方法区分大小写,并可以指定查找的起始位置。

const numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(3)); // 输出 true
console.log(numbers.includes(6)); // 输出 false

77. 什么是 JavaScript 中的 Function.prototype.apply() 方法?

答案
Function.prototype.apply() 方法用于调用一个函数,指定 this 的值,并以数组的形式传递参数。

解析
call 方法类似,但参数以数组形式传递,而不是逐个传递。

function greet(greeting) {
    console.log(`${greeting}, ${this.name}`);
}

const person = { name: 'Alice' };
greet.apply(person, ['Hello']); // 输出 'Hello, Alice'

78. 如何在 JavaScript 中实现深拷贝?

答案
深拷贝是指复制一个对象及其所有嵌套对象的值,而不仅仅是引用。

解析
可以通过递归来实现深拷贝,或者使用 JSON.parse(JSON.stringify(obj)) 方法,但后者不支持函数、日期等类型。

function deepClone(obj) {
    if (obj === null || typeof obj !== 'object') {
        return obj; // 基本类型直接返回
    }

    const clone = Array.isArray(obj) ? [] : {};
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            clone[key] = deepClone(obj[key]); // 递归复制
        }
    }
    return clone;
}

const original = { a: 1, b: { c: 2 } };
const copied = deepClone(original);
console.log(copied); // 输出 { a: 1, b: { c: 2 } }

79. 解释 JavaScript 中的 Array.prototype.reduce() 方法。

答案
Array.prototype.reduce() 方法用于对数组中的每个元素执行一个函数,并将其结果汇总为单一的值。

解析
该方法需要一个回调函数和一个初始值。

const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 输出 10

80. 如何使用 window.onloadDOMContentLoaded 事件?

答案
window.onloadDOMContentLoaded 是用来处理页面加载的事件。

解析

  • window.onload:在页面的所有内容(包括图像、样式表等)加载完成后触发。
  • DOMContentLoaded:在初始的 HTML 文档被完全加载和解析后触发,不需要等待样式表和图像加载完成。
window.onload = function() {
    console.log('All resources finished loading!');
};

document.addEventListener('DOMContentLoaded', function() {
    console.log('DOM fully loaded and parsed!');
});

81. 解释 JavaScript 中的 Array.prototype.fill() 方法。

答案
Array.prototype.fill() 方法用于用静态值填充数组的所有元素,从指定的起始索引到结束索引。

解析
该方法会修改原数组并返回它。

const arr = [1, 2, 3, 4];
arr.fill(0, 1, 3); // 从索引 1 到 3 填充 0
console.log(arr); // 输出 [1, 0, 0, 4]

82. 什么是 JavaScript 中的 WeakRef

答案
WeakRef 是 ES2021 引入的一个构造函数,它创建一个对对象的弱引用。

解析
弱引用不会阻止垃圾回收,如果没有其他强引用,目标对象会被回收。

let obj = { name: 'Alice' };
const weakRef = new WeakRef(obj);

// 手动触发垃圾回收
obj = null; // 现在没有强引用,obj 可以被回收

// 使用 weakRef.get() 获取对象
console.log(weakRef.get()); // 可能输出 undefined,因为 obj 可能已被回收

83. 解释 JavaScript 中的 Promise.any() 方法。

答案
Promise.any() 方法接受一个 Promise 可迭代对象并返回一个 Promise,该 Promise 解析为第一个成功的 Promise 的结果。

解析
如果所有 Promise 都被拒绝,则返回的 Promise 将被拒绝,并返回一个 AggregateError。

const promise1 = Promise.reject('Error 1');
const promise2 = Promise.resolve('Success 2');
const promise3 = Promise.reject('Error 3');

Promise.any([promise1, promise2, promise3])
    .then(result => console.log(result)) // 输出 'Success 2'
    .catch(error => console.log(error));

84. 如何在 JavaScript 中使用 Object.assign() 方法?

答案
Object.assign() 方法用于将一个或多个源对象的可枚举属性复制到目标对象。

解析
该方法返回目标对象,并可以用于合并对象。

const target = { a: 1 };
const source = { b: 2, c: 3 };
const returnedTarget = Object.assign(target, source);

console.log(target); // 输出 { a: 1, b: 2, c: 3 }
console.log(returnedTarget); // 输出 { a: 1, b: 2, c: 3 }

85. 解释 JavaScript 中的 Array.prototype.shift() 方法。

答案
Array.prototype.shift() 方法用于删除数组的第一个元素,并返回该元素的值。

解析
该方法会修改原数组,长度减 1。

const fruits = ['Apple', 'Banana', 'Cherry'];
const first = fruits.shift();
console.log(first); // 输出 'Apple'
console.log(fruits); // 输出 ['Banana', 'Cherry']

86. 什么是 JavaScript 中的 Array.prototype.unshift() 方法?

答案
Array.prototype.unshift() 方法用于在数组的开头添加一个或多个元素,并返回新数组的长度。

解析
该方法会修改原数组。

const fruits = ['Banana', 'Cherry'];
const newLength = fruits.unshift('Apple');
console.log(fruits); // 输出 ['Apple', 'Banana', 'Cherry']
console.log(newLength); // 输出 3

87. 讲解 JavaScript 中的 String.prototype.includes() 方法。

答案
String.prototype.includes() 方法用于判断一个字符串是否包含另一个指定的字符串,返回布尔值。

解析
该方法是区分大小写的,并可以指定查找的起始位置。

const str = 'Hello, world!';
console.log(str.includes('world')); // 输出 true
console.log(str.includes('World')); // 输出 false

88. 如何在 JavaScript 中使用 new 关键字?

答案
new 关键字用于创建一个用户定义的对象类型的实例或构造函数的实例。

解析
使用 new 关键字时会创建一个新对象,调用构造函数并返回该对象。

function Person(name) {
    this.name = name;
}

const alice = new Person('Alice');
console.log(alice.name); // 输出 'Alice'

89. 解释 JavaScript 中的 SetMap

答案
Set 是一种集合类型,用于存储唯一值,而 Map 是用来存储键值对的对象。

解析

  • Set:不允许重复的值,可以存储任何类型的对象。
  • Map:键可以是任何类型的对象,并保留插入顺序。
const mySet = new Set([1, 2, 3, 3]);
console.log(mySet); // 输出 Set { 1, 2, 3 }

const myMap = new Map();
myMap.set('key1', 'value1');
console.log(myMap.get('key1')); // 输出 'value1'

90. 什么是 JavaScript 中的 Symbol 数据类型?

答案
Symbol 是 ES6 引入的一种原始数据类型,表示唯一且不可变的值。

解析
Symbol 通常用于对象的属性键,以避免属性冲突。

const sym1 = Symbol('description');
const sym2 = Symbol('description');

console.log(sym1 === sym2); // 输出 false

const obj = {
    [sym1]: 'value1'
};

console.log(obj[sym1]); // 输出 'value1'

91. 解释 JavaScript 中的 Array.prototype.reverse() 方法。

答案
Array.prototype.reverse() 方法用于反转数组中元素的顺序,直接修改原数组。

解析
该方法返回反转后的数组。

const numbers = [1, 2, 3, 4];
numbers.reverse();
console.log(numbers); // 输出 [4, 3, 2, 1]

92. 什么是 JavaScript 中的 fetch API?

答案
fetch API 是用于发起网络请求的现代接口,基于 Promise。

解析
它支持各种 HTTP 请求,并能处理响应。

fetch('https://api.example.com/data')
    .then(response => {
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        return response.json();
    })
    .then(data => console.log(data))
    .catch(error => console.error('Fetch error:', error));

93. 如何在 JavaScript 中实现数组去重?

答案
可以使用 Setfilter 方法实现数组去重。

解析
使用 Set 是最简单的去重方法。

const numbers = [1, 2, 2, 3, 4, 4];
const uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers); // 输出 [1, 2, 3, 4]

94. 解释 JavaScript 中的 Array.prototype.sort() 方法。

答案
Array.prototype.sort() 方法用于对数组进行排序,默认按字符编码顺序进行排序。

解析
可以传入自定义的排序函数。

const numbers = [4, 2, 3, 1];
numbers.sort((a, b) => a - b);
console.log(numbers); // 输出 [1, 2, 3, 4]

95. 什么是 JavaScript 的模块化?

答案
模块化是将代码分割成独立模块的过程,每个模块可以单独开发、测试和维护。

解析
ES6 引入了 importexport 语法来实现模块化。

// module.js
export const pi = 3.14;
export function add(x, y) {
    return x + y;
}

// main.js
import { pi, add } from './module.js';
console.log(pi); // 输出 3.14
console.log(add(2, 3)); // 输出 5

96. 解释 JavaScript 中的 Object.entries() 方法。

答案
Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组。

解析
每个键值对都是一个数组,第一项是键,第二项是值。

const obj = { a: 1, b: 2 };
const entries = Object.entries(obj);
console.log(entries); // 输出 [['a', 1], ['b', 2]]

97. 什么是 JavaScript 的高阶函数?

答案
高阶函数是指接受一个或多个函数作为参数,或返回一个函数的函数。

解析
高阶函数可以用于抽象或封装操作。

function higherOrderFunction(callback) {
    callback();
}

function sayHello() {
    console.log('Hello!');
}

higherOrderFunction(sayHello); // 输出 'Hello!'

98. 解释 JavaScript 中的 Object.values() 方法。

答案
Object.values() 方法返回一个给定对象自身可枚举属性值的数组。

解析
该方法的返回值是一个数组,包含对象的所有值。

const obj = { a: 1, b: 2 };
const values = Object.values(obj);
console.log(values); // 输出 [1, 2]

99. 如何在 JavaScript 中实现节流(Throttling)?

答案
节流是一种控制函数执行频率的技术,确保在一定时间内只能执行一次。

解析
可以使用时间戳或定时器来实现节流。

function throttle(func, limit) {
    let lastFunc;
    let lastRan;

    return function(...args) {
        if (!lastRan) {
            func.apply(this, args);
            lastRan = Date.now();
        } else {
            clearTimeout(lastFunc);
            lastFunc = setTimeout(() => {
                if (Date.now() - lastRan >= limit) {
                    func.apply(this, args);
                    lastRan = Date.now();
                }
            }, limit - (Date.now() - lastRan));
        }
    };
}

// 用法示例
window.addEventListener('resize', throttle(() => {
    console.log('Resize event');
}, 1000));

100. 解释 JavaScript 中的 IteratorGenerator

答案

  • Iterator:是一种访问集合中元素的抽象接口,提供 next() 方法以返回集合的下一个值和状态。
  • Generator:是一种特殊的函数,可以中断执行并在以后的调用中继续执行,使用 function* 语法定义。

解析

function* generatorFunction() {
    yield 'Hello';
    yield 'World';
}

const generator = generatorFunction();
console.log(generator.next()); // 输出 { value: 'Hello', done: false }
console.log(generator.next()); // 输出 { value: 'World', done: false }
console.log(generator.next()); // 输出 { value: undefined, done: true }

101. 什么是闭包(Closure)?请给出示例。

答案
闭包是一个函数和其词法环境的组合,使得函数能够访问其外部函数的作用域中的变量。

解析
闭包可以用于保护变量不被外部访问,或在异步编程中保存状态。

function makeCounter() {
    let count = 0; // 私有变量
    return function() {
        count++;
        return count;
    };
}

const counter = makeCounter();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2

102. 解释 JavaScript 中的事件循环(Event Loop)。

答案
事件循环是 JavaScript 中处理异步操作的机制,允许单线程的 JavaScript 代码非阻塞地执行。

解析
事件循环管理调用栈和任务队列,当调用栈为空时,它会从任务队列中取出任务执行。

console.log('Start');

setTimeout(() => {
    console.log('Timeout');
}, 0);

Promise.resolve().then(() => {
    console.log('Promise');
});

console.log('End');
// 输出顺序:Start -> End -> Promise -> Timeout

103. 如何使用 setTimeoutsetInterval

答案
setTimeoutsetInterval 均用于调度异步操作。

解析

  • setTimeout:在指定的延迟时间后执行一次回调函数。
  • setInterval:按照指定的时间间隔重复执行回调函数。
setTimeout(() => {
    console.log('Executed after 1 second');
}, 1000); // 1秒后执行

const intervalId = setInterval(() => {
    console.log('Executed every 2 seconds');
}, 2000); // 每2秒执行

// 使用 clearInterval 取消
// clearInterval(intervalId);

104. 什么是 this 关键字?它的值如何确定?

答案
this 是 JavaScript 中的一个关键字,指向当前执行上下文中的对象。

解析
this 的值取决于函数的调用方式:

  • 在全局上下文中,this 指向全局对象(在浏览器中是 window)。
  • 在对象的方法中,this 指向调用该方法的对象。
  • 在构造函数中,this 指向新创建的对象。
  • 在事件处理函数中,this 指向事件的目标元素。

105. 解释 JavaScript 中的 Object.freeze() 方法。

答案
Object.freeze() 方法用于冻结一个对象,使其不可被修改。

解析
冻结后,无法添加、删除或修改对象的属性。

const obj = { name: 'Alice' };
Object.freeze(obj);
obj.name = 'Bob'; // 不会生效
console.log(obj.name); // 输出 'Alice'

106. 如何在 JavaScript 中创建一个单例模式?

答案
单例模式确保一个类只有一个实例,并提供一个全局访问点。

解析
可以使用闭包或模块模式实现单例。

const Singleton = (function() {
    let instance;
    
    function createInstance() {
        const object = new Object('I am the instance');
        return object;
    }
    
    return {
        getInstance: function() {
            if (!instance) {
                instance = createInstance();
            }
            return instance;
        }
    };
})();

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // 输出 true

107. 解释 JavaScript 中的 Array.prototype.splice() 方法。

答案
Array.prototype.splice() 方法用于添加、删除或替换数组中的元素。

解析
该方法会修改原数组,并返回被删除的元素。

const fruits = ['Apple', 'Banana', 'Cherry'];
const removed = fruits.splice(1, 1, 'Orange'); // 从索引 1 开始,删除 1 个元素,添加 'Orange'
console.log(fruits); // 输出 ['Apple', 'Orange', 'Cherry']
console.log(removed); // 输出 ['Banana']

108. 如何在 JavaScript 中进行数组的扁平化?

答案
可以使用 Array.prototype.flat() 方法或递归实现数组的扁平化。

解析
flat 方法可以指定深度。

const nestedArray = [1, [2, [3, 4]]];
const flatArray = nestedArray.flat(2); // 深度为 2 的扁平化
console.log(flatArray); // 输出 [1, 2, 3, 4]

109. 什么是 JavaScript 中的 Promise,它的状态有哪些?

答案
Promise 是表示异步操作的对象,可能在未来的某个时刻完成并返回结果。

解析
Promise 有三种状态:

  • Pending:初始状态,表示操作尚未完成。
  • Fulfilled:操作成功完成,返回结果。
  • Rejected:操作失败,返回错误信息。

110. 如何使用 asyncawait 处理异步编程?

答案
asyncawait 是用于处理异步代码的关键字,使异步代码的书写方式更接近同步。

解析
async 函数返回一个 Promise,await 用于等待 Promise 解析。

async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Error:', error);
    }
}
fetchData();

111. 什么是 JavaScript 中的 Array.prototype.slice() 方法?

答案
Array.prototype.slice() 方法用于返回数组的一个浅拷贝,包含从开始索引到结束索引(不包括结束索引)之间的元素。

解析
该方法不会修改原数组。

const fruits = ['Apple', 'Banana', 'Cherry'];
const sliced = fruits.slice(1, 3); // 从索引 1 到 3 提取
console.log(sliced); // 输出 ['Banana', 'Cherry']
console.log(fruits); // 原数组未被修改

112. 解释 JavaScript 中的 String.prototype.split() 方法。

答案
String.prototype.split() 方法用于将字符串分割为子字符串,并返回一个数组。

解析
可以指定分隔符和可选的限制返回数组的长度。

const str = 'Hello,World,JavaScript';
const arr = str.split(','); // 以逗号分割
console.log(arr); // 输出 ['Hello', 'World', 'JavaScript']

113. 如何在 JavaScript 中实现数组的反转?

答案
可以使用 Array.prototype.reverse() 方法来反转数组。

解析
该方法会直接修改原数组。

const numbers = [1, 2, 3, 4];
numbers.reverse();
console.log(numbers); // 输出 [4, 3, 2, 1]

114. 什么是 JavaScript 中的 this 绑定?

答案
this 绑定是指在执行函数时如何确定 this 的值。

解析
this 的值取决于函数的调用方式:

  • 在全局上下文中,this 指向全局对象。
  • 在对象的方法中,this 指向调用该方法的对象。
  • 在构造函数中,this 指向新创建的对象。
  • 在事件处理函数中,this 通常指向事件的目标元素。

115. 解释 JavaScript 中的 MapSet 的区别。

答案

  • Map:存储键值对,键可以是任何类型,保持插入顺序。
  • Set:存储唯一值,不允许重复的值。

解析
两者都是 ES6 引入的集合类型,适合不同的使用场景。

const myMap = new Map();
myMap.set('key1', 'value1');
console.log(myMap.get('key1')); // 输出 'value1'

const mySet = new Set([1, 2, 2, 3]);
console.log(mySet); // 输出 Set { 1, 2, 3 }

116. 什么是 JavaScript 中的 Promise.all() 方法?

答案
Promise.all() 方法接受一个 Promise 可迭代对象,并返回一个 Promise,该 Promise 解析为所有输入的 Promise 的结果数组。

解析
如果任何 Promise 被拒绝,则返回的 Promise 将被拒绝。

const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);

Promise.all([promise1, promise2, promise3]).then(values => {
    console.log(values); // 输出 [1, 2, 3]
}).catch(error => {
    console.error('Error:', error);
});

117. 解释 JavaScript 中的 for...of 循环的用法。

答案
for...of 循环用于遍历可迭代对象的值,如数组、字符串、Map、Set 等。

解析
它提供了一种简洁的方式来访问元素。

const array = [1, 2, 3];
for (const value of array) {
    console.log(value); // 输出 1, 2, 3
}

const str = 'hello';
for (const char of str) {
    console.log(char); // 输出 'h', 'e', 'l', 'l', 'o'
}

118. 如何在 JavaScript 中处理错误?

答案
可以使用 try...catch 语句来捕获和处理错误。

解析
try 块中放置可能抛出错误的代码,catch 块用于处理错误。

try {
    const result = riskyFunction(); // 可能抛出错误
} catch (error) {
    console.error('Error occurred:', error);
}

119. 什么是 JavaScript 中的 async 函数?

答案
async 函数是 ES2017 引入的函数声明方式,返回一个 Promise。

解析
async 函数内部,可以使用 await 关键字来等待 Promise 的解析。

async function fetchData() {
    return 'Data fetched'; // 包装为 Promise
}

fetchData().then(data => console.log(data)); // 输出 'Data fetched'

120. 解释 JavaScript 中的 Object.keys() 方法。

答案
Object.keys() 方法返回一个给定对象自身可枚举属性的键组成的数组。

解析
该方法只返回对象的可枚举属性,不包括原型链中的属性。

const obj = { a: 1, b: 2 };
const keys = Object.keys(obj);
console.log(keys); // 输出 ['a', 'b']

121. 什么是 JavaScript 中的 Object.assign() 方法?

答案
Object.assign() 方法用于将一个或多个源对象的可枚举属性复制到目标对象。

解析
该方法返回目标对象,并且会修改目标对象。

const target = { a: 1 };
const source = { b: 2, c: 3 };
const returnedTarget = Object.assign(target, source);
console.log(target); // 输出 { a: 1, b: 2, c: 3 }

122. 解释 JavaScript 中的 Array.prototype.reduce() 方法。

答案
Array.prototype.reduce() 方法用于对数组中的每个元素执行一个函数,并将结果汇总为单一的值。

解析
该方法接受一个回调函数和一个可选的初始值。

const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 输出 10

123. 如何在 JavaScript 中实现深拷贝?

答案
可以通过递归或使用 JSON.parse(JSON.stringify(obj)) 来实现深拷贝,但后者不支持函数或特殊对象。

解析
以下是使用递归的实现:

function deepClone(obj) {
    if (obj === null || typeof obj !== 'object') {
        return obj; // 基本类型直接返回
    }

    const clone = Array.isArray(obj) ? [] : {};
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            clone[key] = deepClone(obj[key]); // 递归复制
        }
    }
    return clone;
}

const original = { a: 1, b: { c: 2 } };
const copied = deepClone(original);
console.log(copied); // 输出 { a: 1, b: { c: 2 } }

124. 什么是 JavaScript 的模块化?如何实现?

答案
模块化是将代码分割成独立模块的过程,每个模块可以独立开发、测试和维护。

解析
在 ES6 中,可以使用 importexport 来实现模块化。

// module.js
export const pi = 3.14;
export function add(x, y) {
    return x + y;
}

// main.js
import { pi, add } from './module.js';
console.log(pi); // 输出 3.14
console.log(add(2, 3)); // 输出 5

125. 解释 JavaScript 中的 Set 数据结构。

答案
Set 是一种集合类型,用于存储唯一值,不允许重复。

解析
Set 可以存储任何类型的值,包括对象。

const mySet = new Set([1, 2, 2, 3]);
console.log(mySet); // 输出 Set { 1, 2, 3 }
mySet.add(4);
console.log(mySet.has(2)); // 输出 true

126. 什么是 JavaScript 中的“驼峰命名法”?

答案
驼峰命名法是一种命名约定,其中多个单词连接在一起,第一个单词以小写字母开头,后面的单词以大写字母开头。

解析
例如:myVariableNamegetUserInfo

127. 如何在 JavaScript 中创建一个简单的计时器?

答案
可以使用 setTimeoutsetInterval 来创建计时器。

解析
以下是一个简单的计时器示例:

let count = 0;
const intervalId = setInterval(() => {
    count++;
    console.log(`Timer: ${count} seconds`);
    if (count === 5) {
        clearInterval(intervalId); // 停止计时器
    }
}, 1000); // 每秒输出一次

128. 解释 JavaScript 中的 Promise.race() 方法。

答案
Promise.race() 方法返回一个 Promise,该 Promise 解析或拒绝为第一个完成的 Promise 的结果。

解析
无论是成功还是失败,返回的 Promise 都会在第一个 Promise 完成后立即完成。

const promise1 = new Promise((resolve) => setTimeout(resolve, 500, 'First'));
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'Second'));

Promise.race([promise1, promise2]).then((value) => {
    console.log(value); // 输出 'Second'
});

129. 什么是 JavaScript 的 nullundefined

答案

  • null:表示“无”或“空值”,是一个赋值类型,表示变量已被定义但没有值。
  • undefined:表示“未定义”,即变量已声明但没有被赋值。

解析
两者都表示缺失的值,但在语义上有所不同。

let a = null; // 明确赋值为空
let b; // 声明但未赋值
console.log(a); // 输出 null
console.log(b); // 输出 undefined

130. 解释 JavaScript 中的 Array.prototype.every() 方法。

答案
Array.prototype.every() 方法测试数组中的所有元素是否都通过指定的测试函数。

解析
如果所有元素都满足条件,返回 true;否则返回 false

const numbers = [1, 2, 3, 4];
const allPositive = numbers.every(num => num > 0);
console.log(allPositive); // 输出 true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值