当前位置: 首页 > news >正文

前端 JavaScript 面试题大全(含答案及解析)

前端 JavaScript 面试题大全(含答案及解析)

一、JavaScript 基础与核心概念

1.1 变量与作用域

题目1:var、let、const 的区别

答案

// 1. 变量提升
console.log(a); // undefined
var a = 1;
console.log(b); // ReferenceError
let b = 2;// 2. 重复声明
var c = 1;
var c = 2; // 允许let d = 1;
let d = 2; // SyntaxError// 3. 块级作用域
{var e = 1;let f = 2;
}
console.log(e); // 1
console.log(f); // ReferenceError// 4. 暂时性死区
let g = 1;
{console.log(g); // ReferenceErrorlet g = 2;
}// 5. const 必须初始化且不能重新赋值
const h = 1;
h = 2; // TypeError

解析

  • var:函数作用域,存在变量提升,可重复声明
  • let:块级作用域,不存在变量提升,不可重复声明,存在暂时性死区
  • const:块级作用域,必须初始化,不可重新赋值(但可修改对象属性)
题目2:闭包及其应用场景

答案

// 闭包示例:函数能够记住并访问所在的词法作用域
function createCounter() {let count = 0;return function() {count++;return count;};
}const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2// 应用场景1:模块模式
const calculator = (function() {let result = 0;return {add: function(x) { result += x; },getResult: function() { return result; }};
})();// 应用场景2:私有变量
function Person(name) {const privateName = name;this.getName = function() {return privateName;};
}

解析

  • 闭包定义:函数能够访问其声明时的词法作用域,即使函数在其它地方执行
  • 内存泄漏风险:不当使用闭包可能导致内存无法释放
  • 实际应用:模块化、私有变量、柯里化、防抖节流等

1.2 数据类型与类型转换

题目3:== 与 === 的区别

答案

// == 宽松相等(类型转换)
console.log(1 == '1');    // true
console.log(true == 1);   // true
console.log(null == undefined); // true
console.log('' == 0);     // true// === 严格相等(无类型转换)
console.log(1 === '1');   // false
console.log(true === 1);  // false
console.log(null === undefined); // false
console.log('' === 0);    // false// 特殊情况
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true

解析

  • == 会进行类型转换,遵循复杂的转换规则
  • === 不会进行类型转换,类型不同直接返回 false
  • 最佳实践:大多数情况下使用 ===,避免隐式类型转换带来的问题
题目4:数据类型检测方法

答案

// typeof - 基本类型检测
console.log(typeof 123);        // "number"
console.log(typeof 'hello');    // "string"  
console.log(typeof true);       // "boolean"
console.log(typeof undefined);  // "undefined"
console.log(typeof null);       // "object" (历史遗留问题)
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// Array.isArray - 数组检测
console.log(Array.isArray([]));      // true
console.log(Array.isArray({}));      // false// Object.prototype.toString - 精确类型检测
console.log(Object.prototype.toString.call(123));        // "[object Number]"
console.log(Object.prototype.toString.call('hello'));    // "[object String]"
console.log(Object.prototype.toString.call(null));       // "[object Null]"
console.log(Object.prototype.toString.call(undefined));  // "[object Undefined]"
console.log(Object.prototype.toString.call([]));         // "[object Array]"

二、异步编程

2.1 Promise 相关

题目5:Promise 的基本使用

答案

// Promise 创建
const promise = new Promise((resolve, reject) => {setTimeout(() => {Math.random() > 0.5 ? resolve('成功') : reject('失败');}, 1000);
});// Promise 链式调用
promise.then(result => {console.log('then:', result);return result + '!';}).catch(error => {console.log('catch:', error);throw new Error('新的错误');}).then(result => {console.log('第二个then:', result);}).finally(() => {console.log('无论如何都会执行');});// Promise 静态方法
Promise.resolve('立即成功').then(console.log);
Promise.reject('立即失败').catch(console.log);// Promise.all - 全部成功
Promise.all([Promise.resolve(1),Promise.resolve(2)
]).then(results => console.log('all成功:', results)); // [1, 2]// Promise.race - 第一个完成
Promise.race([new Promise(resolve => setTimeout(() => resolve('第一个'), 100)),new Promise(resolve => setTimeout(() => resolve('第二个'), 200))
]).then(result => console.log('race:', result)); // "第一个"
题目6:async/await 错误处理

答案

// 错误处理方式
async function fetchData() {try {const response = await fetch('/api/data');const data = await response.json();return data;} catch (error) {console.error('请求失败:', error);throw error; // 重新抛出错误}
}// 多个异步操作
async function processMultiple() {try {const [user, posts] = await Promise.all([fetchUser(),fetchPosts()]);return { user, posts };} catch (error) {// 任何一个请求失败都会进入catchconsole.error('多个请求失败:', error);}
}// 替代 try-catch 的方式
async function alternativeErrorHandling() {const result = await fetchData().catch(error => {console.error('替代方案:', error);return null;});if (!result) return;// 处理结果
}

2.2 事件循环

题目7:说出以下代码的输出顺序

答案

console.log('1');setTimeout(() => {console.log('2');
}, 0);Promise.resolve().then(() => {console.log('3');
});console.log('4');// 输出顺序: 1 -> 4 -> 3 -> 2

解析

  1. 同步代码:14
  2. 微任务(Promise):3
  3. 宏任务(setTimeout):2

事件循环机制

  • 调用栈:同步代码执行
  • 微任务队列:Promise、MutationObserver、process.nextTick
  • 宏任务队列:setTimeout、setInterval、I/O、UI渲染
  • 执行顺序:调用栈 → 微任务 → 宏任务 → 微任务…

三、面向对象与原型

3.1 原型与继承

题目8:原型链的理解

答案

function Person(name) {this.name = name;
}Person.prototype.sayHello = function() {console.log(`Hello, I'm ${this.name}`);
};function Student(name, grade) {Person.call(this, name);this.grade = grade;
}// 设置原型链
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;Student.prototype.study = function() {console.log(`${this.name} is studying`);
};const student = new Student('Alice', 'A');
student.sayHello(); // "Hello, I'm Alice"
student.study();    // "Alice is studying"// 原型链验证
console.log(student instanceof Student); // true
console.log(student instanceof Person);  // true
console.log(student instanceof Object);  // true

解析

  • prototype:函数的原型对象
  • proto:对象的原型指针(实际使用 Object.getPrototypeOf)
  • 原型链:对象通过 proto 连接形成的链式结构
  • 继承本质:通过原型链实现属性和方法的共享
题目9:Class 与构造函数的区别

答案

// 构造函数方式
function OldPerson(name) {this.name = name;
}OldPerson.prototype.sayHello = function() {console.log(`Hello, ${this.name}`);
};// Class 方式
class NewPerson {constructor(name) {this.name = name;}// 实例方法(在原型上)sayHello() {console.log(`Hello, ${this.name}`);}// 静态方法static createAnonymous() {return new NewPerson('Anonymous');}// Getter/Setterget displayName() {return `Person: ${this.name}`;}
}// 继承对比
class Student extends NewPerson {constructor(name, grade) {super(name); // 必须调用this.grade = grade;}
}

解析

  • Class 是语法糖,本质还是基于原型的继承
  • Class 特点
    • 更清晰的语法
    • 必须使用 new 调用
    • 方法不可枚举
    • 内置的 extends 和 super
    • 支持静态方法和私有字段

四、ES6+ 新特性

4.1 解构与扩展运算符

题目10:解构赋值的应用

答案

// 数组解构
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first, second, rest); // 1 2 [3,4,5]// 对象解构
const person = { name: 'Alice', age: 25, city: 'Beijing' };
const { name, age, country = 'China' } = person;
console.log(name, age, country); // Alice 25 China// 函数参数解构
function printUser({ name, age = 18 }) {console.log(`${name} is ${age} years old`);
}// 嵌套解构
const company = {name: 'Tech Corp',employees: [{ name: 'Alice', department: 'Engineering' }]
};
const { employees: [{ department }] } = company;// 扩展运算符
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = [...arr1, ...arr2];const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };

4.2 箭头函数

题目11:箭头函数与普通函数的区别

答案

const obj = {name: 'Alice',// 普通函数regularFunc: function() {console.log('Regular:', this.name);},// 箭头函数arrowFunc: () => {console.log('Arrow:', this.name); // undefined},// 嵌套函数中的thisnestedFunc: function() {const innerArrow = () => {console.log('Nested Arrow:', this.name); // Alice};innerArrow();}
};// 其它区别
function Regular() {}
const Arrow = () => {};console.log(new Regular()); // Regular实例
console.log(new Arrow());   // TypeError// arguments 对象
function regular() { console.log(arguments); }
const arrow = () => { console.log(arguments); }; // ReferenceError

解析

  • this 绑定:箭头函数没有自己的 this,继承外层作用域
  • 构造函数:箭头函数不能用作构造函数
  • arguments:箭头函数没有 arguments 对象
  • 原型:箭头函数没有 prototype 属性

五、函数式编程

5.1 高阶函数

题目12:实现常用的高阶函数

答案

// map 实现
Array.prototype.myMap = function(callback) {const result = [];for (let i = 0; i < this.length; i++) {result.push(callback(this[i], i, this));}return result;
};// filter 实现  
Array.prototype.myFilter = function(callback) {const result = [];for (let i = 0; i < this.length; i++) {if (callback(this[i], i, this)) {result.push(this[i]);}}return result;
};// reduce 实现
Array.prototype.myReduce = function(callback, initialValue) {let accumulator = initialValue !== undefined ? initialValue : this[0];let startIndex = initialValue !== undefined ? 0 : 1;for (let i = startIndex; i < this.length; i++) {accumulator = callback(accumulator, this[i], i, this);}return accumulator;
};// 使用示例
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.myMap(x => x * 2);
const evens = numbers.myFilter(x => x % 2 === 0);
const sum = numbers.myReduce((acc, curr) => acc + curr, 0);

5.2 柯里化与组合

题目13:实现函数柯里化

答案

// 柯里化函数
function curry(fn) {return function curried(...args) {if (args.length >= fn.length) {return fn.apply(this, args);} else {return function(...args2) {return curried.apply(this, args.concat(args2));};}};
}// 使用示例
function add(a, b, c) {return a + b + c;
}const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6
console.log(curriedAdd(1)(2, 3)); // 6// 实际应用:创建特定功能的函数
const add5 = curriedAdd(5);
console.log(add5(10)(15)); // 30

六、性能与优化

6.1 防抖与节流

题目14:实现防抖和节流函数

答案

// 防抖:在事件触发 n 秒后执行,如果 n 秒内重复触发则重新计时
function debounce(fn, delay) {let timer = null;return function(...args) {clearTimeout(timer);timer = setTimeout(() => {fn.apply(this, args);}, delay);};
}// 节流:在 n 秒内只执行一次
function throttle(fn, delay) {let lastTime = 0;return function(...args) {const now = Date.now();if (now - lastTime >= delay) {fn.apply(this, args);lastTime = now;}};
}// 使用示例
const debouncedSearch = debounce((query) => {console.log('搜索:', query);
}, 300);const throttledScroll = throttle(() => {console.log('滚动处理');
}, 100);// 输入框搜索防抖
searchInput.addEventListener('input', (e) => {debouncedSearch(e.target.value);
});// 滚动事件节流  
window.addEventListener('scroll', throttledScroll);

6.2 内存管理

题目15:常见的内存泄漏场景及避免

答案

// 1. 意外的全局变量
function leak1() {leakedVar = '这是一个全局变量'; // 没有 var/let/const
}// 2. 闭包使用不当
function leak2() {const bigData = new Array(1000000).fill('*');return function() {console.log(bigData.length); // bigData 无法被回收};
}// 3. 定时器未清理
function leak3() {const data = { /* 大数据 */ };setInterval(() => {console.log(data);}, 1000);// 应该保存 timer 并在适当时机清除
}// 4. DOM 引用未清理
function leak4() {const elements = {button: document.getElementById('button'),// 即使从 DOM 移除,elements 仍持有引用};// 解决方案:手动解除引用// elements.button = null;
}// 5. 事件监听器未移除
function leak5() {const button = document.getElementById('button');button.addEventListener('click', handleClick);// 应该在组件卸载时移除// button.removeEventListener('click', handleClick);
}

七、实用编程题

7.1 数组去重

答案

// 多种数组去重方法
const array = [1, 2, 2, 3, 4, 4, 5];// 1. Set (最简洁)
const unique1 = [...new Set(array)];// 2. filter + indexOf
const unique2 = array.filter((item, index) => array.indexOf(item) === index
);// 3. reduce
const unique3 = array.reduce((acc, curr) => {return acc.includes(curr) ? acc : [...acc, curr];
}, []);// 4. 对象属性 (适用于基本类型)
const unique4 = Object.keys(array.reduce((acc, curr) => {acc[curr] = true;return acc;
}, {}));console.log(unique1); // [1, 2, 3, 4, 5]

7.2 深拷贝实现

答案

function deepClone(obj, hash = new WeakMap()) {// 基本类型或 nullif (obj === null || typeof obj !== 'object') {return obj;}// 循环引用检测if (hash.has(obj)) {return hash.get(obj);}// 日期对象if (obj instanceof Date) {return new Date(obj);}// 正则表达式if (obj instanceof RegExp) {return new RegExp(obj);}// 数组if (Array.isArray(obj)) {const cloneArr = [];hash.set(obj, cloneArr);obj.forEach((item, index) => {cloneArr[index] = deepClone(item, hash);});return cloneArr;}// 普通对象const cloneObj = Object.create(Object.getPrototypeOf(obj));hash.set(obj, cloneObj);for (let key in obj) {if (obj.hasOwnProperty(key)) {cloneObj[key] = deepClone(obj[key], hash);}}return cloneObj;
}// 使用示例
const original = {name: 'Alice',hobbies: ['reading', 'coding'],address: {city: 'Beijing',coordinates: { lat: 39.9, lng: 116.4 }}
};const cloned = deepClone(original);

面试技巧与准备建议

💡 面试准备建议

  1. 理解原理而非死记硬背:理解 JavaScript 的运行机制比记住 API 更重要
  2. 手写代码练习:经常练习手写常见函数和方法
  3. 关注性能:了解常见性能问题和优化方案
  4. 掌握调试技巧:熟练使用浏览器开发者工具
  5. 跟进新特性:关注 ES6+ 的新特性和最佳实践

🎯 答题技巧

  1. 先思考再回答:理解问题本质,组织好语言再回答
  2. 结合实际场景:用实际项目经验来支撑你的答案
  3. 承认不知道:对于不了解的问题诚实承认,展示学习能力
  4. 代码规范:手写代码时注意命名规范和代码风格

这份面试题涵盖了 JavaScript 的核心概念和常见考点,建议结合实际编码练习来加深理解。祝你面试顺利!

http://www.dtcms.com/a/491222.html

相关文章:

  • 网站页面设计报告wordpress 门户插件
  • 国外营销型网站建设容城网站建设
  • 将.idea取消git托管
  • YOLOv1和YOLOv2目标检测算法总结
  • 系统移植篇之uboot-4:UART
  • net和cn哪个做网站好wordpress企业主题 视频
  • 石家庄网站排名优化360网站建设服务
  • 苍穹外卖-购物车 前端修改(小程序主页与购物车模块显示不一致)
  • 聊聊 Unity(小白专享、C# 小程序 之 小算盘、计算器)
  • 江苏金安建设公司网站在线设计平台官网
  • 专业网站建设公司哪里济南兴田德润什么活动电子商务网站的整个建设流程
  • 【2025年湖南省赛misc复盘】
  • 北京建设教育协会官方网站做产品推广得网站
  • 牙刮匙与牙周治疗疗效的相关性分析
  • 三星XR头显发布会正式敲定,苹果/Meta/微美全息竞逐AR底层核心卡位“军备竞赛”
  • 【C++进阶系列】:类型转换和IO流
  • 卡板技术支持 东莞网站建设动态设计是什么意思
  • 宠物服务平台(程序+文档)
  • Maven再次认识
  • 【STM32项目开源】基于STM32的智能厨房环境监控系统
  • 策略模式详情
  • 省级网站 开发建设 资质企业员工培训课程
  • VS Code settings.json配置(终端篇)
  • 好看的静态网站网页制作设计教程
  • Spring Boot API文档与自动化测试详解
  • 哈尔滨龙彩做网站多少钱做网站怎么样引流
  • Redis实战篇---添加缓存(店铺类型添加缓存需求)
  • 泸州百拓网站建设英文网站数据库如何建设
  • 河北电子商务网站建设互联网营销策略有哪些
  • 苏州专业网站设计制作公司湛江企业网站怎么建设