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

Javascript面试题及详细答案150道之(121-135)

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

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

在这里插入图片描述

文章目录

  • 一、本文面试题目录
      • 121. 如何在JavaScript中实现一个简单的装饰器(Decorator)?
      • 122. JavaScript中`Proxy`的作用是什么?
      • 123. 如何在JavaScript中实现一个简单的观察者模式(Observer Pattern)?
      • 124. JavaScript中`Object.freeze()`、`Object.seal()`和`Object.preventExtensions()`的区别是什么?
      • 125. 如何在JavaScript中实现一个简单的有限状态机(Finite State Machine)?
      • 126. JavaScript中`WeakSet`和`Set`的区别是什么?
      • 127. 如何在JavaScript中实现一个简单的二进制搜索(Binary Search)?
      • 128. JavaScript中`Array.prototype.sort()`的排序原理是什么?
      • 129. 如何在JavaScript中实现一个简单的链表反转?
      • 130. JavaScript中`BigInt`的作用是什么?
      • 131. 如何在JavaScript中实现一个简单的队列(Queue)?
      • 132. JavaScript中`Object.assign()`和展开语法`...`的区别是什么?
      • 133. 如何在JavaScript中实现一个简单的栈(Stack)?
      • 134. JavaScript中`Map`和普通对象的区别是什么?
      • 135. 如何在JavaScript中实现一个简单的二叉搜索树(Binary Search Tree)?
  • 二、150道面试题目录列表

一、本文面试题目录

121. 如何在JavaScript中实现一个简单的装饰器(Decorator)?

装饰器原理
在不修改原函数的前提下,扩展其功能。JavaScript中的装饰器本质是高阶函数。

代码示例

// 日志装饰器
function logDecorator(target, name, descriptor) {const originalMethod = descriptor.value;descriptor.value = function(...args) {console.log(`调用 ${name} 方法,参数:`, args);const result = originalMethod.apply(this, args);console.log(`${name} 方法返回:`, result);return result;};return descriptor;
}class Calculator {@logDecoratoradd(a, b) {return a + b;}
}const calc = new Calculator();
calc.add(3, 5); // 输出日志:调用 add 方法 → 返回 8

手动实现装饰器效果

function timeDecorator(func) {return function(...args) {const start = Date.now();const result = func.apply(this, args);const end = Date.now();console.log(`函数执行时间: ${end - start}ms`);return result;};
}function sum(a, b) {return a + b;
}const timedSum = timeDecorator(sum);
timedSum(1000, 2000); // 输出执行时间

122. JavaScript中Proxy的作用是什么?

Proxy
用于创建对象的代理,拦截并自定义对该对象的基本操作(如属性访问、赋值、枚举等)。

核心拦截器

拦截器触发时机
get(target, prop, receiver)读取属性
set(target, prop, value, receiver)设置属性
has(target, prop)in操作符
deleteProperty(target, prop)delete操作符
ownKeys(target)Object.getOwnPropertyNames()
apply(target, thisArg, args)函数调用(代理函数时)

代码示例

// 数据验证代理
const person = {name: 'Alice',age: 30
};const validator = {set(target, prop, value) {if (prop === 'age' && typeof value!== 'number') {throw new TypeError('Age must be a number');}target[prop] = value;return true;}
};const proxyPerson = new Proxy(person, validator);
proxyPerson.age = 31; // 正常设置
proxyPerson.age = 'thirty'; // 抛出错误

应用场景

  • 数据绑定(如Vue 3的响应式系统)。
  • 访问控制(私有属性)。
  • 性能监控(拦截方法调用计时)。

123. 如何在JavaScript中实现一个简单的观察者模式(Observer Pattern)?

观察者模式
定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会收到通知。

代码示例

class EventEmitter {constructor() {this.events = new Map();}// 注册观察者on(event, callback) {if (!this.events.has(event)) {this.events.set(event, []);}this.events.get(event).push(callback);}// 发布事件emit(event, data) {if (this.events.has(event)) {this.events.get(event).forEach(callback => callback(data));}}// 取消订阅off(event, callback) {if (this.events.has(event)) {const callbacks = this.events.get(event);const index = callbacks.indexOf(callback);if (index!== -1) {callbacks.splice(index, 1);}}}
}// 使用示例
const emitter = new EventEmitter();// 订阅者1
emitter.on('message', (data) => {console.log('订阅者1收到:', data);
});// 订阅者2
emitter.on('message', (data) => {console.log('订阅者2收到:', data);
});// 发布事件
emitter.emit('message', 'Hello, Observers!');
// 输出:
// 订阅者1收到: Hello, Observers!
// 订阅者2收到: Hello, Observers!

124. JavaScript中Object.freeze()Object.seal()Object.preventExtensions()的区别是什么?

核心区别

方法不可添加新属性不可删除现有属性不可修改现有属性不可修改原型
Object.preventExtensions()
Object.seal()❌(可修改值)
Object.freeze()

代码示例

const obj = { a: 1, b: 2 };// preventExtensions
const preventObj = Object.preventExtensions(obj);
preventObj.c = 3; // 静默失败(严格模式下抛出错误)
delete preventObj.a; // 可以删除
preventObj.a = 10; // 可以修改// seal
const sealedObj = Object.seal(obj);
sealedObj.c = 3; // 失败
delete sealedObj.a; // 失败
sealedObj.a = 10; // 可以修改// freeze
const frozenObj = Object.freeze(obj);
frozenObj.c = 3; // 失败
delete frozenObj.a; // 失败
frozenObj.a = 10; // 失败

检测方法

Object.isExtensible(obj); // 是否可扩展
Object.isSealed(obj); // 是否被seal
Object.isFrozen(obj); // 是否被freeze

125. 如何在JavaScript中实现一个简单的有限状态机(Finite State Machine)?

状态机实现
定义状态、转换规则和动作,确保状态转换的合法性。

代码示例

class StateMachine {constructor(initialState, transitions) {this.currentState = initialState;this.transitions = transitions;}// 触发状态转换transition(event) {const transitions = this.transitions[this.currentState];const nextState = transitions[event];if (!nextState) {throw new Error(`Invalid transition: ${this.currentState} -> ${event}`);}this.currentState = nextState;return this.currentState;}// 获取当前状态getState() {return this.currentState;}
}// 使用示例
const trafficLight = new StateMachine('green', {green: { timer: 'yellow' },yellow: { timer: 'red' },red: { timer: 'green' }
});console.log(trafficLight.getState()); // "green"
trafficLight.transition('timer'); // 绿灯 → 黄灯
trafficLight.transition('timer'); // 黄灯 → 红灯

126. JavaScript中WeakSetSet的区别是什么?

核心区别

特性WeakSetSet
元素类型仅对象(弱引用)任意类型
垃圾回收元素被GC时自动从WeakSet移除需手动删除元素
迭代支持不支持keys()values()支持所有迭代方法
大小获取size属性size属性
应用场景存储临时关联的对象通用集合操作

代码示例

// WeakSet
const ws = new WeakSet();
const obj = {};
ws.add(obj);
console.log(ws.has(obj)); // true// 当obj被GC时,ws中的引用自动消失// Set
const s = new Set();
s.add(1);
s.add('a');
console.log(s.size); // 2
console.log(Array.from(s)); // [1, "a"]

弱引用示例

let element = document.createElement('div');
const ws = new WeakSet([element]);// 当element被DOM移除且无其他引用时
element = null; // element可被GC,WeakSet中的引用自动消失

127. 如何在JavaScript中实现一个简单的二进制搜索(Binary Search)?

二分查找实现
在有序数组中查找目标值,时间复杂度O(log n)。

代码示例

function binarySearch(arr, target) {let left = 0;let right = arr.length - 1;while (left <= right) {const mid = Math.floor((left + right) / 2);if (arr[mid] === target) {return mid; // 找到目标} else if (arr[mid] < target) {left = mid + 1; // 目标在右半部分} else {right = mid - 1; // 目标在左半部分}}return -1; // 未找到
}// 使用示例
const sortedArray = [1, 3, 5, 7, 9, 11];
console.log(binarySearch(sortedArray, 7)); // 3
console.log(binarySearch(sortedArray, 4)); // -1

递归实现

function binarySearchRecursive(arr, target, left = 0, right = arr.length - 1) {if (left > right) return -1;const mid = Math.floor((left + right) / 2);if (arr[mid] === target) {return mid;} else if (arr[mid] < target) {return binarySearchRecursive(arr, target, mid + 1, right);} else {return binarySearchRecursive(arr, target, left, mid - 1);}
}

128. JavaScript中Array.prototype.sort()的排序原理是什么?

sort()方法
默认将元素转换为字符串并按Unicode码点排序,可传入比较函数自定义排序规则。

默认排序

const arr = [10, 1, 5];
arr.sort(); // 结果:[1, 10, 5](按字符串排序)

比较函数
compare(a, b)返回值规则:

  • < 0a排在b
  • > 0a排在b
  • = 0:顺序不变

代码示例

// 数字升序
const numbers = [5, 3, 8, 1];
numbers.sort((a, b) => a - b); // [1, 3, 5, 8]// 字符串长度降序
const strings = ['apple', 'banana', 'cherry'];
strings.sort((a, b) => b.length - a.length); // ["banana", "cherry", "apple"]// 对象属性排序
const people = [{ name: 'Alice', age: 25 },{ name: 'Bob', age: 20 },{ name: 'Charlie', age: 30 }
];
people.sort((a, b) => a.age - b.age); // 按年龄升序

浏览器实现差异

  • Chrome/V8:长度≤10的数组用插入排序,>10用快速排序。
  • Firefox:归并排序。
  • Safari:快速排序。

129. 如何在JavaScript中实现一个简单的链表反转?

链表反转
遍历链表,逐个改变节点的指针方向。

代码示例

class Node {constructor(value) {this.value = value;this.next = null;}
}function reverseLinkedList(head) {let prev = null;let current = head;while (current) {const nextNode = current.next; // 保存下一个节点current.next = prev; // 反转指针prev = current; // 移动prevcurrent = nextNode; // 移动current}return prev; // 返回新头节点
}// 使用示例
const head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);const reversedHead = reverseLinkedList(head);
// 链表变为: 3 -> 2 -> 1

递归实现

function reverseLinkedListRecursive(head) {if (!head ||!head.next) {return head;}const newHead = reverseLinkedListRecursive(head.next);head.next.next = head; // 反转指针head.next = null; // 断开原指针return newHead;
}

130. JavaScript中BigInt的作用是什么?

BigInt
ES2020引入的新数据类型,用于表示任意精度的整数,解决Number类型的精度限制。

基本用法

// 创建BigInt
const bigNum1 = 123456789012345678901234567890n;
const bigNum2 = BigInt('123456789012345678901234567890');// 运算
const result = bigNum1 + bigNum2; // 246913578024691357802469135780n// 比较
console.log(bigNum1 === bigNum2); // false
console.log(bigNum1 < bigNum2); // true// 与Number混合运算需转换
const num = 100;
const mixedResult = bigNum1 + BigInt(num); // 123456789012345678901234567990n

注意事项

  • 不能与Number直接运算,需通过BigInt()转换。
  • 不支持Math对象的方法。
  • 比较时需注意类型(10n!== 10)。

应用场景

  • 高精度计算(如金融、科学计算)。
  • 处理超过Number.MAX_SAFE_INTEGER的ID或时间戳。

131. 如何在JavaScript中实现一个简单的队列(Queue)?

队列实现
先进先出(FIFO)的数据结构,支持入队、出队、查看队首等操作。

代码示例

class Queue {constructor() {this.items = [];}// 入队enqueue(element) {this.items.push(element);}// 出队dequeue() {if (this.isEmpty()) return null;return this.items.shift();}// 获取队首元素front() {if (this.isEmpty()) return null;return this.items[0];}// 判断队列是否为空isEmpty() {return this.items.length === 0;}// 获取队列长度size() {return this.items.length;}
}// 使用示例
const queue = new Queue();
queue.enqueue(1);
queue.enqueue(2);
console.log(queue.dequeue()); // 1
console.log(queue.front()); // 2

优化实现(避免shift()的性能开销)

class OptimizedQueue {constructor() {this.items = {};this.head = 0;this.tail = 0;}enqueue(element) {this.items[this.tail] = element;this.tail++;}dequeue() {if (this.isEmpty()) return null;const item = this.items[this.head];delete this.items[this.head];this.head++;return item;}// 其他方法同上...
}

132. JavaScript中Object.assign()和展开语法...的区别是什么?

核心区别

特性Object.assign()展开语法...
语法函数调用操作符
返回值修改后的目标对象新创建的对象
执行方式运行时执行编译时展开
处理Symbol属性
应用场景合并对象、修改目标对象创建新对象、解构赋值

代码示例

const obj1 = { a: 1 };
const obj2 = { b: 2 };// Object.assign()
const assigned = Object.assign(obj1, obj2);
console.log(obj1); // { a: 1, b: 2 }(目标对象被修改)
console.log(assigned === obj1); // true// 展开语法
const spread = {...obj1,...obj2 };
console.log(obj1); // { a: 1 }(原对象未修改)
console.log(spread); // { a: 1, b: 2 }
console.log(spread === obj1); // false// 处理getter/setter
const objWithGetter = {get value() { return 10; }
};const assignedWithGetter = Object.assign({}, objWithGetter);
console.log(assignedWithGetter.value); // 10(值被复制)const spreadWithGetter = {...objWithGetter };
console.log(spreadWithGetter.value); // 10(值被复制)

133. 如何在JavaScript中实现一个简单的栈(Stack)?

栈实现
后进先出(LIFO)的数据结构,支持入栈、出栈、查看栈顶等操作。

代码示例

class Stack {constructor() {this.items = [];}// 入栈push(element) {this.items.push(element);}// 出栈pop() {if (this.isEmpty()) return undefined;return this.items.pop();}// 获取栈顶元素peek() {if (this.isEmpty()) return undefined;return this.items[this.items.length - 1];}// 判断栈是否为空isEmpty() {return this.items.length === 0;}// 获取栈的大小size() {return this.items.length;}
}// 使用示例
const stack = new Stack();
stack.push(1);
stack.push(2);
console.log(stack.pop()); // 2
console.log(stack.peek()); // 1

基于对象的优化实现

class OptimizedStack {constructor() {this.items = {};this.count = 0;}push(element) {this.items[this.count] = element;this.count++;}pop() {if (this.isEmpty()) return undefined;this.count--;const value = this.items[this.count];delete this.items[this.count];return value;}// 其他方法同上...
}

134. JavaScript中Map和普通对象的区别是什么?

核心区别

特性Map普通对象
键的类型任意类型(包括对象、函数)仅字符串或Symbol
迭代支持支持keys()values()entries()需手动转换为数组迭代
顺序保证保持插入顺序不保证顺序(ES6+字符串键按插入顺序,但非强制)
性能频繁增删键值对时性能更好适合少量固定键的场景
大小获取size属性需手动计算(如Object.keys().length

代码示例

// Map
const map = new Map();
const keyObj = {};
map.set(keyObj, 'value associated with keyObj');
console.log(map.get(keyObj)); // "value associated with keyObj"
console.log(map.size); // 1// 普通对象
const obj = {};
obj[keyObj] = 'value'; // 键被转换为字符串"[object Object]"
console.log(obj[keyObj]); // "value"
console.log(obj["[object Object]"]); // "value"

迭代对比

const map = new Map([['a', 1],['b', 2]
]);for (const [key, value] of map) {console.log(key, value); // "a 1", "b 2"
}const obj = { a: 1, b: 2 };
for (const key in obj) {console.log(key, obj[key]); // "a 1", "b 2"
}

135. 如何在JavaScript中实现一个简单的二叉搜索树(Binary Search Tree)?

二叉搜索树实现
每个节点的左子树值小于节点值,右子树值大于节点值。

代码示例

class Node {constructor(value) {this.value = value;this.left = null;this.right = null;}
}class BinarySearchTree {constructor() {this.root = null;}// 插入节点insert(value) {const newNode = new Node(value);if (!this.root) {this.root = newNode;return this;}let current = this.root;while (true) {if (value === current.value) return undefined;if (value < current.value) {if (!current.left) {current.left = newNode;return this;}current = current.left;} else {if (!current.right) {current.right = newNode;return this;}current = current.right;}}}// 查找节点find(value) {if (!this.root) return false;let current = this.root;while (current) {if (value === current.value) return current;if (value < current.value) {current = current.left;} else {current = current.right;}}return false;}// 中序遍历(从小到大排序)inOrderTraversal(node = this.root, result = []) {if (node) {this.inOrderTraversal(node.left, result);result.push(node.value);this.inOrderTraversal(node.right, result);}return result;}
}// 使用示例
const bst = new BinarySearchTree();
bst.insert(5);
bst.insert(3);
bst.insert(7);
console.log(bst.find(3)); // 节点 { value: 3, left: null, right: null }
console.log(bst.inOrderTraversal()); // [3, 5, 7]

二、150道面试题目录列表

文章序号Javascript面试题150道
1Javascript面试题及答案150道(001-015)
2Javascript面试题及答案150道(016-030)
3Javascript面试题及答案150道(031-045)
4Javascript面试题及答案150道(046-060)
5Javascript面试题及答案150道(061-075)
6Javascript面试题及答案150道(076-090)
7Javascript面试题及答案150道(091-105)
8Javascript面试题及答案150道(106-120)
9Javascript面试题及答案150道(121-135)
10Javascript面试题及答案150道(136-150)
http://www.dtcms.com/a/341463.html

相关文章:

  • 医学影像分析中的持续学习:近期进展与未来展望综述|文献速递-深度学习人工智能医疗图像
  • 42-Python基础语法-2
  • Lecture 5 GPUs课程笔记
  • Leetcode 深度优先搜索 (9)
  • Kafka-Kraft
  • leetcode3 无重复字符的最长子串
  • vue2封装日期选择组件--有时间选择版本
  • 创建Vue项目的不同方式及项目规范化配置
  • Playwright 与 Scrapy 的实际应用场景能力分析
  • 深入理解 Spring 的 @ControllerAdvice
  • 【AI应用】修改向量数据库Milvus默认密码
  • KylinV10服务器版和桌面版SVN搭建步骤
  • python中view把矩阵维度降低的时候是什么一个排序顺序
  • 深度解析LangChain:LLM应用开发利器
  • Linux: network: arp: arp_accept
  • linux内核 - 内存管理单元(MMU)与地址翻译(二)
  • 直播预告|鸿蒙全场景开发指南
  • 【GPT入门】第50课 LlamaFacotory 客观评估模型效果
  • 接美国血统(中序、后序→前序)
  • 如何让FastAPI任务系统在失败时自动告警并自我修复?
  • Frida 动态 Hook 安卓 WebView 与第三方内核完全指南
  • 一种数字相机中的自动曝光算法
  • 01-Docker概述
  • 多摄像头多算法智能监控系统设计与实现
  • 关于 preprocessing.scale 函数
  • 机器语言、操作系统与硬件执行:深入解析计算机的底层逻辑
  • 【C++】模版(初阶)
  • 从“怀疑作弊”到“实锤取证”:在线面试智能监考重塑招聘公信力
  • CLEAN 函数
  • HTML 简明教程