Javascript面试题及详细答案150道之(046-060)

前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux... 。

前后端面试题-专栏总目录

文章目录

  • 一、本文面试题目录
      • [46. 如何实现对象的深拷贝(考虑多种数据类型)?](#46. 如何实现对象的深拷贝(考虑多种数据类型)?)
      • [47. 什么是模块化?CommonJS和ES6 Module有什么区别?](#47. 什么是模块化?CommonJS和ES6 Module有什么区别?)
      • [48. 如何判断两个对象是否相等(深相等)?](#48. 如何判断两个对象是否相等(深相等)?)
      • [49. 什么是事件委托(事件代理)?有什么好处?](#49. 什么是事件委托(事件代理)?有什么好处?)
      • [50. 如何阻止事件冒泡和默认行为?](#50. 如何阻止事件冒泡和默认行为?)
      • [51. 什么是变量提升和函数提升?](#51. 什么是变量提升和函数提升?)
      • [52. 什么是JSON?JSON和JavaScript对象有什么区别?](#52. 什么是JSON?JSON和JavaScript对象有什么区别?)
      • [53. 如何获取当前时间并格式化?](#53. 如何获取当前时间并格式化?)
      • [54. 什么是递归函数?使用递归要注意什么?](#54. 什么是递归函数?使用递归要注意什么?)
      • [55. 如何实现数组的findIndex方法?](#55. 如何实现数组的findIndex方法?)
      • [56. 什么是Set和Map?它们有什么特点?](#56. 什么是Set和Map?它们有什么特点?)
      • [57. 如何实现数组的filter方法?](#57. 如何实现数组的filter方法?)
      • [58. 什么是严格模式(strict mode)?如何启用?有什么限制?](#58. 什么是严格模式(strict mode)?如何启用?有什么限制?)
      • [59. 什么是迭代器(Iterator)?它有什么作用?](#59. 什么是迭代器(Iterator)?它有什么作用?)
      • [60. 如何实现数组的reduce方法?](#60. 如何实现数组的reduce方法?)
  • 二、150道面试题目录列表

一、本文面试题目录

46. 如何实现对象的深拷贝(考虑多种数据类型)?

实现一个能处理多种数据类型(对象、数组、日期、正则等)的深拷贝函数:

javascript 复制代码
function deepClone(obj, hash = new WeakMap()) {
  if (obj === null || typeof obj!== 'object') return obj;
  if (hash.has(obj)) return hash.get(obj); // 处理循环引用
  let cloneObj;
  // 处理日期
  if (obj instanceof Date) {
    cloneObj = new Date(obj);
    hash.set(obj, cloneObj);
    return cloneObj;
  }
  // 处理正则
  if (obj instanceof RegExp) {
    cloneObj = new RegExp(obj.source, obj.flags);
    hash.set(obj, cloneObj);
    return cloneObj;
  }
  // 处理数组和对象
  cloneObj = Array.isArray(obj)? [] : {};
  hash.set(obj, cloneObj);
  // 递归拷贝属性
  Reflect.ownKeys(obj).forEach(key => {
    cloneObj[key] = deepClone(obj[key], hash);
  });
  return cloneObj;
}

47. 什么是模块化?CommonJS和ES6 Module有什么区别?

模块化是将代码拆分为独立的模块,便于复用和维护。

区别:

  • 语法:CommonJS用require()导入、module.exports导出;ES6 Module用import导入、export导出。
  • 加载方式:CommonJS是运行时加载(动态),ES6 Module是编译时加载(静态)。
  • 作用域:CommonJS模块中,模块是一个函数作用域;ES6 Module是块级作用域。
  • this指向:CommonJS模块中this指向当前模块;ES6 Module中this是undefined。

示例:

javascript 复制代码
// CommonJS
const moduleA = require('./moduleA');
module.exports = { foo: 'bar' };

// ES6 Module
import { moduleB } from './moduleB';
export const baz = 'baz';

48. 如何判断两个对象是否相等(深相等)?

深相等是指两个对象的所有层级属性都相等。实现方法:

javascript 复制代码
function deepEqual(a, b) {
  // 基本类型直接比较
  if (a === b) return true;
  // 处理null
  if (a === null || b === null) return false;
  // 类型不同返回false
  if (typeof a!== typeof b) return false;
  // 处理对象和数组
  if (typeof a === 'object') {
    // 获取属性名
    const keysA = Reflect.ownKeys(a);
    const keysB = Reflect.ownKeys(b);
    if (keysA.length!== keysB.length) return false;
    // 递归比较每个属性
    return keysA.every(key => deepEqual(a[key], b[key]));
  }
  return false;
}

49. 什么是事件委托(事件代理)?有什么好处?

事件委托是将子元素的事件处理委托给父元素,利用事件冒泡原理,当子元素触发事件时,父元素能捕获到并处理。

好处:

  • 减少事件监听器数量,提高性能。
  • 动态添加的子元素也能触发事件,无需重新绑定。

示例代码:

javascript 复制代码
// 父元素ul代理li的点击事件
const ul = document.querySelector('ul');
ul.addEventListener('click', (e) => {
  if (e.target.tagName === 'LI') { // 判断触发事件的是li
    console.log('点击了li:', e.target.textContent);
  }
});

50. 如何阻止事件冒泡和默认行为?

  • 阻止事件冒泡:
    • 标准浏览器:event.stopPropagation()
    • IE低版本:event.cancelBubble = true
  • 阻止默认行为(如表单提交、链接跳转):
    • 标准浏览器:event.preventDefault()
    • IE低版本:event.returnValue = false
    • 也可在事件处理函数中返回false(仅适用于部分事件,如onclick)。

示例代码:

javascript 复制代码
document.getElementById('btn').addEventListener('click', (e) => {
  e.stopPropagation(); // 阻止冒泡
  e.preventDefault(); // 阻止默认行为(若按钮有默认行为)
});

51. 什么是变量提升和函数提升?

  • 变量提升:使用var声明的变量,会被提升到作用域顶部,声明提升但赋值不提升。
  • 函数提升:函数声明会被整体提升到作用域顶部,可在声明前调用。函数表达式(如var fn = function(){})只有变量提升,没有函数提升。

示例代码:

javascript 复制代码
// 变量提升
console.log(x); // undefined(var声明提升,赋值未提升)
var x = 10;

// 函数提升
foo(); // 能调用,函数声明提升
function foo() {
  console.log('foo');
}

// 函数表达式不提升
bar(); // 报错,bar是变量,此时值为undefined
var bar = function() {
  console.log('bar');
};

52. 什么是JSON?JSON和JavaScript对象有什么区别?

JSON(JavaScript Object Notation)是一种轻量级数据交换格式,基于JavaScript对象字面量语法,但有严格规定。

区别:

  • JSON是字符串,用于数据传输;JavaScript对象是内存中的数据结构。
  • JSON的键必须用双引号包裹;JavaScript对象的键可不用引号或用单/双引号。
  • JSON的值不能有函数、undefined、Symbol;JavaScript对象可以。
  • JSON的尾逗号不允许;JavaScript对象允许。

示例:

json 复制代码
// JSON
{ "name": "Jack", "age": 25 }
javascript 复制代码
// JavaScript对象
const obj = { name: 'Jack', age: 25, sayHi() {} };

53. 如何获取当前时间并格式化?

可使用Date对象获取当前时间,然后自定义格式化函数。

示例代码:

javascript 复制代码
function formatDate(date = new Date(), format = 'yyyy-MM-dd HH:mm:ss') {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');
  return format.replace('yyyy', year)
   .replace('MM', month)
   .replace('dd', day)
   .replace('HH', hours)
   .replace('mm', minutes)
   .replace('ss', seconds);
}
console.log(formatDate()); // 2025-07-21 10:30:45(当前时间)

54. 什么是递归函数?使用递归要注意什么?

递归函数是在函数内部调用自身的函数,用于解决可分解为相同子问题的问题(如阶乘、斐波那契数列)。

注意:

  • 必须有终止条件,否则会导致栈溢出。
  • 递归深度不宜过深,可能影响性能。

示例代码:

javascript 复制代码
// 计算阶乘
function factorial(n) {
  if (n === 1) return 1; // 终止条件
  return n * factorial(n - 1);
}
console.log(factorial(5)); // 120

55. 如何实现数组的findIndex方法?

findIndex()返回数组中满足条件的第一个元素的索引,若没有则返回-1。

示例代码:

javascript 复制代码
Array.prototype.myFindIndex = function(callback, thisArg) {
  for (let i = 0; i < this.length; i++) {
    if (callback.call(thisArg, this[i], i, this)) {
      return i;
    }
  }
  return -1;
};
const arr = [10, 20, 30];
console.log(arr.myFindIndex(item => item > 15)); // 1

56. 什么是Set和Map?它们有什么特点?

  • Set:是值的集合,特点是值唯一,没有重复值,可用于数组去重。
    常用方法:add()、delete()、has()、clear()、size属性。
  • Map:是键值对的集合,键可以是任意类型(对象、基本类型等),与对象不同,对象的键只能是字符串或Symbol。
    常用方法:set()、get()、delete()、has()、clear()、size属性。

示例代码:

javascript 复制代码
// Set
const set = new Set([1, 2, 2, 3]);
console.log(set.size); // 3
set.add(4);
console.log(set.has(2)); // true

// Map
const map = new Map();
const key = { id: 1 };
map.set(key, 'value');
console.log(map.get(key)); // value

57. 如何实现数组的filter方法?

filter()创建一个新数组,包含所有通过测试(回调函数返回true)的元素。

示例代码:

javascript 复制代码
Array.prototype.myFilter = function(callback, thisArg) {
  const result = [];
  for (let i = 0; i < this.length; i++) {
    if (callback.call(thisArg, this[i], i, this)) {
      result.push(this[i]);
    }
  }
  return result;
};
const arr = [1, 2, 3, 4, 5];
console.log(arr.myFilter(item => item % 2 === 0)); // [2, 4]

58. 什么是严格模式(strict mode)?如何启用?有什么限制?

严格模式是JavaScript的一种限制性更强的执行模式,使代码更规范、更安全。

启用:在脚本或函数顶部添加'use strict';

限制:

  • 变量必须声明后使用。
  • 不能删除变量、函数或函数参数。
  • 禁止this指向全局对象(普通函数调用时this为undefined)。
  • 禁止在函数内部声明eval和arguments为变量。

示例代码:

javascript 复制代码
'use strict';
// x = 10; // 报错,变量未声明
function strictFunc() {
  'use strict';
  console.log(this); // undefined(普通调用时)
}
strictFunc();

59. 什么是迭代器(Iterator)?它有什么作用?

迭代器是一种接口,为各种数据结构提供统一的遍历方式,任何实现了Iterator接口的数据结构都可被for...of循环遍历。

迭代器有一个next()方法,返回一个包含value(当前值)和done(是否遍历结束)的对象。

作用:使不同数据结构(数组、Set、Map等)的遍历方式统一。

示例代码:

javascript 复制代码
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

60. 如何实现数组的reduce方法?

reduce()对数组中的每个元素执行回调函数,将其缩减为单个值,可指定初始值。

示例代码:

javascript 复制代码
Array.prototype.myReduce = function(callback, initialValue) {
  let accumulator = initialValue;
  let startIndex = 0;
  // 若未提供初始值,使用数组第一个元素作为初始值
  if (initialValue === undefined) {
    accumulator = this[0];
    startIndex = 1;
  }
  for (let i = startIndex; i < this.length; i++) {
    accumulator = callback(accumulator, this[i], i, this);
  }
  return accumulator;
};
const arr = [1, 2, 3, 4];
console.log(arr.myReduce((acc, cur) => acc + cur, 0)); // 10

二、150道面试题目录列表

文章序号 Javascript面试题150道
1 Javascript面试题及答案150道(001-015)
2 Javascript面试题及答案150道(016-030)
3 Javascript面试题及答案150道(031-045)
4 Javascript面试题及答案150道(046-060)
5 Javascript面试题及答案150道(061-075)
6 Javascript面试题及答案150道(076-090)
7 Javascript面试题及答案150道(091-105)
8 Javascript面试题及答案150道(106-120)
9 Javascript面试题及答案150道(121-135)
10 Javascript面试题及答案150道(136-150)
相关推荐
快起来别睡了36 分钟前
深入浅出 Event Loop:前端工程师必须掌握的运行机制
前端·javascript
user2975258761237 分钟前
别再用关键字搜了!手搓一个Vite插件,为页面上的标签打上标记
前端·javascript·vite
典学长编程38 分钟前
前端开发(HTML,CSS,VUE,JS)从入门到精通!第五天(jQuery函数库)
javascript·css·ajax·html·jquery
尝尝你的优乐美1 小时前
原来前端二进制数组有这么多门道
前端·javascript·面试
前端_yu小白1 小时前
Vue2实现docx,xlsx,pptx预览
开发语言·javascript·ecmascript
金金金__1 小时前
事件循环-原理篇
javascript·浏览器
CF14年老兵2 小时前
2025 年 React 在 Web 开发中的核心地位:优势、应用场景与顶级案例
javascript·react.js·redux
还是大剑师兰特2 小时前
Javascript面试题及详细答案150道之(031-045)
大剑师·javascript面试题
橙某人2 小时前
📆基于Grid布局完成最精简的日期组件
前端·javascript