
答案: 闭包是一个函数与其词法环境的组合。换句话说,闭包可以让一个函数访问并操作其外部函数的变量,即使外部函数已经返回。
解析: 当函数被创建时,它会记住其作用域(即变量的上下文),即使外部函数已经执行完毕,闭包仍然可以访问这些变量。
function outerFunction() {
let outerVariable = 'Hello';
return function innerFunction() {
console.log(outerVariable);
};
}
const inner = outerFunction();
inner(); // 输出 'Hello'this 关键字的含义是什么?答案:
this 关键字指向当前执行上下文中的对象。在不同的情况下,this 的值是不同的。
解析:
this 指向全局对象(在浏览器中是 window)。this 指向调用该方法的对象。this 指向新创建的对象。this 通常指向触发事件的元素。答案: 原型是 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'答案: 事件冒泡和事件捕获是两种事件传播机制。
解析:
document 对象。document 对象向下传播到目标元素。可以通过 addEventListener 方法的第三个参数来控制是捕获还是冒泡,默认为 false(冒泡)。
element.addEventListener('click', function(event) {
// 处理点击事件
}, false); // 冒泡答案: 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);
});答案: 异步编程允许程序在等待某些操作完成时继续执行其他操作,以提高效率。
解析:
在 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();let 和 const 的作用域及用法。答案:
let 和 const 是 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答案: 防抖和节流都是控制函数执行频率的技术。
解析:
// 防抖实现
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));
}
};
}map、filter 和 reduce 方法。答案:
map、filter 和 reduce 是数组的高阶函数,用于处理数组数据。
解析:
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); // 15async/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();localStorage 和 sessionStorage?答案:
localStorage 和 sessionStorage 是 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'null 和 undefined 的区别是什么?答案:
null 和 undefined 都表示“无”或“没有值”,但它们在 JavaScript 中是不同的类型。
解析:
undefined:表示变量被声明但未赋值,或对象属性不存在。null:表示一个无值的对象,通常用于指示变量应有的值为空。let a;
console.log(a); // 输出 undefined
let b = null;
console.log(b); // 输出 null答案: 防止重复提交通常通过禁用按钮或使用标志变量来实现。
解析: 可以在表单提交时禁用提交按钮,避免用户多次点击。
document.getElementById('submitBtn').addEventListener('click', function() {
this.disabled = true; // 禁用按钮
// 处理表单提交逻辑
});答案: 事件委托是一种事件处理模式,将事件处理程序附加到父元素,而不是直接附加到每个子元素上。
解析: 当子元素触发事件时,事件会冒泡到父元素,父元素的事件处理程序可以处理这些事件。这种方式可以提高性能,尤其是在动态添加子元素的情况下。
document.getElementById('parent').addEventListener('click', function(event) {
if (event.target.matches('.child')) {
console.log('Child element clicked:', event.target);
}
});答案:
在 JavaScript 中,异步函数的错误可以通过 try/catch 语句或 .catch() 方法来处理。
解析:
async/await 时,可以在 try/catch 块中捕获错误。.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));答案: 模块化是将代码分割成独立的模块,每个模块拥有自己的作用域,可以更好地管理代码的组织和依赖关系。
解析:
在 JavaScript 中,可以使用 ES6 模块(import 和 export)或 CommonJS(require 和 module.exports)进行模块化。
// ES6 模块
// module.js
export const myFunction = () => { console.log('Hello'); };
// main.js
import { myFunction } from './module.js';
myFunction(); // 输出 'Hello'答案: 浅拷贝和深拷贝是复制对象的两种方式。
解析:
// 浅拷贝
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,原对象不受影响setTimeout 和 setInterval 的区别。答案:
setTimeout 和 setInterval 都用于定时执行代码,但有明显的区别。
解析:
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);答案: 懒加载是一种优化技术,推迟加载不必要的内容,直到需要时才加载。
解析: 可以使用 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);
});bind、call 和 apply 方法。答案:
bind、call 和 apply 是函数对象的方法,用于改变函数的 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'答案: 箭头函数是 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()); // 输出 42Promise.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);
});async 函数?答案:
async 函数是 ES2017 引入的一种函数声明方式,返回一个 Promise。
解析:
在 async 函数内部,可以使用 await 关键字来等待 Promise 的解析。async 函数会隐式地将返回值包装为 Promise。
async function fetchData() {
return 'Data fetched'; // 这会被包装成 Promise
}
fetchData().then(data => console.log(data)); // 输出 'Data fetched'答案: 深拷贝和浅拷贝用于复制对象,但它们的工作方式不同。
解析:
Object.assign()。JSON.parse(JSON.stringify(obj)) 或者使用 Lodash 的 _.cloneDeep()。应用场景:
答案: 内存泄漏是指程序中不再使用的对象仍被引用,导致无法被垃圾回收器回收。
解析: 常见的内存泄漏情况包括:
处理方式:
setImmediate 和 process.nextTick。答案:
setImmediate 和 process.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 -> ImmediateSymbol 类型。答案:
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'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'答案: 自执行函数(Immediately Invoked Function Expression, IIFE)是一种在定义时立即执行的函数。
解析: IIFE 通常用于创建一个新的作用域,避免变量污染全局作用域。
(function() {
const message = 'Hello, World!';
console.log(message);
})(); // 输出 'Hello, World!'
// console.log(message); // ReferenceError: message is not defined答案: 函数节流是一种控制函数执行频率的技术,确保函数在一定时间内只被执行一次。
解析: 可以使用时间戳或定时器来实现节流。
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));WeakMap 和 WeakSet。答案:
WeakMap 和 WeakSet 是 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 可以被垃圾回收答案: 深度克隆是指复制一个对象及其嵌套对象的所有值,而不是仅复制引用。
解析:
可以使用 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 } }答案: 模块化是将代码分割成小的、可重用的代码单元(模块),每个模块可以独立开发、测试和维护。
解析:
ES6 引入了模块化语法,通过 import 和 export 关键字实现模块的导入与导出。
// 在 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!'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答案:
解绑事件通常通过 removeEventListener 方法实现。
解析:
需要确保传递给 removeEventListener 的函数引用与添加事件监听器时的函数相同。
function handleClick() {
console.log('Clicked!');
}
document.getElementById('myButton').addEventListener('click', handleClick);
// 解绑事件
document.getElementById('myButton').removeEventListener('click', handleClick);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'
});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); // 输出 10for...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'
}答案: 事件总线是一种发布-订阅模式的实现,允许不同组件之间进行通信。
解析:
可以使用对象来存储事件及其处理函数,并提供 on、emit 和 off 方法。
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);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));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']答案: 节流是一种控制函数执行频率的技术,确保在一定时间内只能执行一次。
解析: 可以使用时间戳或定时器来实现节流。
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));Array.prototype.filter() 方法。答案:
Array.prototype.filter() 方法用于创建一个新数组,其中包含所有通过测试的元素。
解析:
该方法接受一个回调函数,回调函数对数组中的每个元素进行测试,返回 true 或 false。
const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // 输出 [2, 4]try...catch 语句在 JavaScript 中的用法。答案:
try...catch 语句用于处理异常,可以捕获在 try 块中发生的错误。
解析:
try 块中的代码会被执行,如果发生错误,则会跳转到 catch 块中进行处理。
try {
const result = riskyFunction(); // 可能抛出错误的函数
} catch (error) {
console.error('Error occurred:', error);
}setTimeout 和 setInterval 的区别?答案:
setTimeout 和 setInterval 都是用于调度延时执行代码的方法,但它们的用法不同。
解析:
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);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 }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);
});答案: 在 JavaScript 中,可以使用回调函数、Promises 和 async/await 来处理异步操作。
解析:
then() 和 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);
}
}
fetchData();Object.keys() 方法。答案:
Object.keys() 方法返回一个由给定对象的自身可枚举属性的键组成的数组。
解析: 该方法只返回对象的可枚举属性,不包括原型链中的属性。
const obj = { a: 1, b: 2, c: 3 };
const keys = Object.keys(obj);
console.log(keys); // 输出 ['a', 'b', 'c']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 -> Timeouttypeof 运算符?答案:
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'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]let 和 const 的作用域?答案:
let 和 const 是 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答案: 闭包是一个函数与其词法环境的组合,允许函数访问外部函数的变量,即使外部函数已经返回。
解析: 闭包可以用于数据封装和私有变量。
function outerFunction() {
let outerVariable = 'Hello';
return function innerFunction() {
console.log(outerVariable);
};
}
const inner = outerFunction();
inner(); // 输出 'Hello'localStorage 和 sessionStorage?答案:
localStorage 和 sessionStorage 是 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'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 }
// ]
});答案: DOM 事件是用户与网页交互时触发的事件,如点击、输入、鼠标移动等。
解析:
可以使用事件监听器(addEventListener)来处理这些事件。
document.getElementById('myButton').addEventListener('click', function() {
console.log('Button clicked!');
});答案: 解构赋值是 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答案: 深拷贝是复制一个对象及其嵌套对象的所有值,而不仅仅是引用。
解析:
可以使用递归、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 } }Array.prototype.reduceRight() 方法。答案:
Array.prototype.reduceRight() 方法从数组的最后一个元素开始,逐个应用回调函数,最终计算出一个单一的值。
解析: 该方法接受一个回调函数和一个初始值,返回最终的计算结果。
const numbers = [1, 2, 3, 4];
const sum = numbers.reduceRight((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 输出 10class 关键字及其用法。答案:
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.'答案: 原型链是 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'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'Array.prototype.every() 方法?答案:
Array.prototype.every() 方法测试数组中的所有元素是否都通过指定的测试函数。
解析:
如果所有元素都满足条件,返回 true;否则返回 false。
const numbers = [1, 2, 3, 4];
const allPositive = numbers.every(num => num > 0);
console.log(allPositive); // 输出 trueArray.prototype.find() 方法。答案:
Array.prototype.find() 方法返回数组中满足提供的测试函数的第一个元素的值。
解析:
如果没有找到满足条件的元素,返回 undefined。
const numbers = [5, 12, 8, 130, 44];
const found = numbers.find(num => num > 10);
console.log(found); // 输出 12this 关键字?答案:
this 关键字指向当前执行上下文中的对象,其值取决于函数的调用方式。
解析:
this 指向全局对象(浏览器中的 window)。this 指向调用该方法的对象。this 指向新创建的对象。this 通常指向事件的目标元素。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答案: 防抖是一种控制频繁事件触发的技术,确保事件在一定时间后执行,如果在这段时间内再次触发,则重新计时。
解析:
可以使用 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));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); // 原数组未被修改答案: 事件冒泡和事件捕获是 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); // 捕获Object.create() 方法。答案:
Object.create() 方法用于创建一个新对象,指定其原型对象。
解析: 该方法接受一个对象作为参数,该对象将作为新对象的原型。
const animal = {
speak() {
console.log('Animal speaks');
}
};
const dog = Object.create(animal);
dog.speak(); // 输出 'Animal speaks'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]答案: 事件委托是一种将事件处理器附加到父元素而不是子元素的技术。
解析: 当子元素触发事件时,事件会冒泡到父元素,父元素的事件处理器可以处理这些事件。这种方式可以提高性能,特别是对于动态添加的子元素。
const parent = document.getElementById('parent');
parent.addEventListener('click', function(event) {
if (event.target.matches('.child')) {
console.log('Child element clicked:', event.target);
}
});Promise 的状态。答案:
Promise 有三种状态: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));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();Array.prototype.includes() 方法。答案:
Array.prototype.includes() 方法用于判断数组是否包含某个值,返回布尔值。
解析: 该方法区分大小写,并可以指定查找的起始位置。
const numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(3)); // 输出 true
console.log(numbers.includes(6)); // 输出 falseFunction.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'答案: 深拷贝是指复制一个对象及其所有嵌套对象的值,而不仅仅是引用。
解析:
可以通过递归来实现深拷贝,或者使用 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 } }Array.prototype.reduce() 方法。答案:
Array.prototype.reduce() 方法用于对数组中的每个元素执行一个函数,并将其结果汇总为单一的值。
解析: 该方法需要一个回调函数和一个初始值。
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 输出 10window.onload 和 DOMContentLoaded 事件?答案:
window.onload 和 DOMContentLoaded 是用来处理页面加载的事件。
解析:
window.onload:在页面的所有内容(包括图像、样式表等)加载完成后触发。DOMContentLoaded:在初始的 HTML 文档被完全加载和解析后触发,不需要等待样式表和图像加载完成。window.onload = function() {
console.log('All resources finished loading!');
};
document.addEventListener('DOMContentLoaded', function() {
console.log('DOM fully loaded and parsed!');
});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]WeakRef?答案:
WeakRef 是 ES2021 引入的一个构造函数,它创建一个对对象的弱引用。
解析: 弱引用不会阻止垃圾回收,如果没有其他强引用,目标对象会被回收。
let obj = { name: 'Alice' };
const weakRef = new WeakRef(obj);
// 手动触发垃圾回收
obj = null; // 现在没有强引用,obj 可以被回收
// 使用 weakRef.get() 获取对象
console.log(weakRef.get()); // 可能输出 undefined,因为 obj 可能已被回收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));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 }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']Array.prototype.unshift() 方法?答案:
Array.prototype.unshift() 方法用于在数组的开头添加一个或多个元素,并返回新数组的长度。
解析: 该方法会修改原数组。
const fruits = ['Banana', 'Cherry'];
const newLength = fruits.unshift('Apple');
console.log(fruits); // 输出 ['Apple', 'Banana', 'Cherry']
console.log(newLength); // 输出 3String.prototype.includes() 方法。答案:
String.prototype.includes() 方法用于判断一个字符串是否包含另一个指定的字符串,返回布尔值。
解析: 该方法是区分大小写的,并可以指定查找的起始位置。
const str = 'Hello, world!';
console.log(str.includes('world')); // 输出 true
console.log(str.includes('World')); // 输出 falsenew 关键字?答案:
new 关键字用于创建一个用户定义的对象类型的实例或构造函数的实例。
解析:
使用 new 关键字时会创建一个新对象,调用构造函数并返回该对象。
function Person(name) {
this.name = name;
}
const alice = new Person('Alice');
console.log(alice.name); // 输出 'Alice'Set 和 Map。答案:
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'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'Array.prototype.reverse() 方法。答案:
Array.prototype.reverse() 方法用于反转数组中元素的顺序,直接修改原数组。
解析: 该方法返回反转后的数组。
const numbers = [1, 2, 3, 4];
numbers.reverse();
console.log(numbers); // 输出 [4, 3, 2, 1]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));答案:
可以使用 Set 或 filter 方法实现数组去重。
解析:
使用 Set 是最简单的去重方法。
const numbers = [1, 2, 2, 3, 4, 4];
const uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers); // 输出 [1, 2, 3, 4]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]答案: 模块化是将代码分割成独立模块的过程,每个模块可以单独开发、测试和维护。
解析:
ES6 引入了 import 和 export 语法来实现模块化。
// 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)); // 输出 5Object.entries() 方法。答案:
Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组。
解析: 每个键值对都是一个数组,第一项是键,第二项是值。
const obj = { a: 1, b: 2 };
const entries = Object.entries(obj);
console.log(entries); // 输出 [['a', 1], ['b', 2]]答案: 高阶函数是指接受一个或多个函数作为参数,或返回一个函数的函数。
解析: 高阶函数可以用于抽象或封装操作。
function higherOrderFunction(callback) {
callback();
}
function sayHello() {
console.log('Hello!');
}
higherOrderFunction(sayHello); // 输出 'Hello!'Object.values() 方法。答案:
Object.values() 方法返回一个给定对象自身可枚举属性值的数组。
解析: 该方法的返回值是一个数组,包含对象的所有值。
const obj = { a: 1, b: 2 };
const values = Object.values(obj);
console.log(values); // 输出 [1, 2]答案: 节流是一种控制函数执行频率的技术,确保在一定时间内只能执行一次。
解析: 可以使用时间戳或定时器来实现节流。
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));Iterator 和 Generator。答案:
next() 方法以返回集合的下一个值和状态。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 }答案: 闭包是一个函数和其词法环境的组合,使得函数能够访问其外部函数的作用域中的变量。
解析: 闭包可以用于保护变量不被外部访问,或在异步编程中保存状态。
function makeCounter() {
let count = 0; // 私有变量
return function() {
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2答案: 事件循环是 JavaScript 中处理异步操作的机制,允许单线程的 JavaScript 代码非阻塞地执行。
解析: 事件循环管理调用栈和任务队列,当调用栈为空时,它会从任务队列中取出任务执行。
console.log('Start');
setTimeout(() => {
console.log('Timeout');
}, 0);
Promise.resolve().then(() => {
console.log('Promise');
});
console.log('End');
// 输出顺序:Start -> End -> Promise -> TimeoutsetTimeout 和 setInterval?答案:
setTimeout 和 setInterval 均用于调度异步操作。
解析:
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);this 关键字?它的值如何确定?答案:
this 是 JavaScript 中的一个关键字,指向当前执行上下文中的对象。
解析:
this 的值取决于函数的调用方式:
this 指向全局对象(在浏览器中是 window)。this 指向调用该方法的对象。this 指向新创建的对象。this 指向事件的目标元素。Object.freeze() 方法。答案:
Object.freeze() 方法用于冻结一个对象,使其不可被修改。
解析: 冻结后,无法添加、删除或修改对象的属性。
const obj = { name: 'Alice' };
Object.freeze(obj);
obj.name = 'Bob'; // 不会生效
console.log(obj.name); // 输出 'Alice'答案: 单例模式确保一个类只有一个实例,并提供一个全局访问点。
解析: 可以使用闭包或模块模式实现单例。
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); // 输出 trueArray.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']答案:
可以使用 Array.prototype.flat() 方法或递归实现数组的扁平化。
解析:
flat 方法可以指定深度。
const nestedArray = [1, [2, [3, 4]]];
const flatArray = nestedArray.flat(2); // 深度为 2 的扁平化
console.log(flatArray); // 输出 [1, 2, 3, 4]Promise,它的状态有哪些?答案:
Promise 是表示异步操作的对象,可能在未来的某个时刻完成并返回结果。
解析:
Promise 有三种状态:
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();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); // 原数组未被修改String.prototype.split() 方法。答案:
String.prototype.split() 方法用于将字符串分割为子字符串,并返回一个数组。
解析: 可以指定分隔符和可选的限制返回数组的长度。
const str = 'Hello,World,JavaScript';
const arr = str.split(','); // 以逗号分割
console.log(arr); // 输出 ['Hello', 'World', 'JavaScript']答案:
可以使用 Array.prototype.reverse() 方法来反转数组。
解析: 该方法会直接修改原数组。
const numbers = [1, 2, 3, 4];
numbers.reverse();
console.log(numbers); // 输出 [4, 3, 2, 1]this 绑定?答案:
this 绑定是指在执行函数时如何确定 this 的值。
解析:
this 的值取决于函数的调用方式:
this 指向全局对象。this 指向调用该方法的对象。this 指向新创建的对象。this 通常指向事件的目标元素。Map 和 Set 的区别。答案:
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 }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);
});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'
}答案:
可以使用 try...catch 语句来捕获和处理错误。
解析:
在 try 块中放置可能抛出错误的代码,catch 块用于处理错误。
try {
const result = riskyFunction(); // 可能抛出错误
} catch (error) {
console.error('Error occurred:', error);
}async 函数?答案:
async 函数是 ES2017 引入的函数声明方式,返回一个 Promise。
解析:
在 async 函数内部,可以使用 await 关键字来等待 Promise 的解析。
async function fetchData() {
return 'Data fetched'; // 包装为 Promise
}
fetchData().then(data => console.log(data)); // 输出 'Data fetched'Object.keys() 方法。答案:
Object.keys() 方法返回一个给定对象自身可枚举属性的键组成的数组。
解析: 该方法只返回对象的可枚举属性,不包括原型链中的属性。
const obj = { a: 1, b: 2 };
const keys = Object.keys(obj);
console.log(keys); // 输出 ['a', 'b']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 }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答案:
可以通过递归或使用 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 } }答案: 模块化是将代码分割成独立模块的过程,每个模块可以独立开发、测试和维护。
解析:
在 ES6 中,可以使用 import 和 export 来实现模块化。
// 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)); // 输出 5Set 数据结构。答案:
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答案: 驼峰命名法是一种命名约定,其中多个单词连接在一起,第一个单词以小写字母开头,后面的单词以大写字母开头。
解析:
例如:myVariableName,getUserInfo。
答案:
可以使用 setTimeout 或 setInterval 来创建计时器。
解析: 以下是一个简单的计时器示例:
let count = 0;
const intervalId = setInterval(() => {
count++;
console.log(`Timer: ${count} seconds`);
if (count === 5) {
clearInterval(intervalId); // 停止计时器
}
}, 1000); // 每秒输出一次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'
});null 和 undefined?答案:
null:表示“无”或“空值”,是一个赋值类型,表示变量已被定义但没有值。undefined:表示“未定义”,即变量已声明但没有被赋值。解析: 两者都表示缺失的值,但在语义上有所不同。
let a = null; // 明确赋值为空
let b; // 声明但未赋值
console.log(a); // 输出 null
console.log(b); // 输出 undefinedArray.prototype.every() 方法。答案:
Array.prototype.every() 方法测试数组中的所有元素是否都通过指定的测试函数。
解析:
如果所有元素都满足条件,返回 true;否则返回 false。
const numbers = [1, 2, 3, 4];
const allPositive = numbers.every(num => num > 0);
console.log(allPositive); // 输出 true