在前端工程师的面试中,尤其是面向一线大厂(如阿里、腾讯、字节、美团等)时,JavaScript 的底层原理与运行机制往往是考察的重点。本文将围绕两个经典而高频的面试题展开:
- 如何手写实现
new操作符? - 函数中的
arguments是什么?它真的是数组吗?
通过这两个问题,我们将深入探讨 JavaScript 中的原型链、构造函数、this 绑定、类数组对象等核心概念,并辅以代码实践与思考延伸,助你真正掌握这些知识点背后的逻辑。
一、手写 new:理解对象实例化的全过程
1.1 new 做了什么?
当你写下:
function Person(name) {
this.name = name;
}
const p = new Person('Alice');
JavaScript 引擎实际上完成了以下四件事:
- 创建一个全新的空对象;
- 将这个新对象的
[[Prototype]](即__proto__)指向构造函数的prototype; - 将构造函数内部的
this绑定到这个新对象,并执行构造函数; - 如果构造函数没有显式返回一个引用类型(对象/数组/函数等),则自动返回新创建的对象。
1.2 手写实现 myNew
基于上述逻辑,我们可以轻松实现自己的 new:
function myNew(constructor, ...args) {
// 1. 创建空对象,继承构造函数的原型
const obj = Object.create(constructor.prototype);
// 2. 执行构造函数,绑定 this
const result = constructor.apply(obj, args);
// 3. 判断是否返回了对象,若是则返回该对象,否则返回新对象
return (typeof result === 'object' && result !== null) ? result : obj;
}
1.3 验证效果
function Car(brand) {
this.brand = brand;
}
const car1 = myNew(Car, 'Tesla');
console.log(car1.brand); // Tesla
console.log(car1 instanceof Car); // true
✅ 完美复刻原生 new 行为!
💡 思考延伸:如果构造函数返回一个基本类型(如
return 42),会发生什么?答案是:依然返回新对象。只有返回非 null 的对象才会覆盖默认行为。
二、arguments:被误解的“类数组”
2.1 什么是 arguments?
在非箭头函数中,arguments 是一个自动可用的局部变量,它包含了调用时传入的所有参数。
function add() {
console.log(arguments); // [1, 2, 3](看起来像数组)
}
add(1, 2, 3);
但它不是真正的数组!它是一个类数组对象(Array-like Object) 。
2.2 类数组 vs 真数组
| 特性 | arguments | 真数组 |
|---|---|---|
有 length 属性 | ✅ | ✅ |
| 可通过索引访问元素 | ✅ | ✅ |
继承自 Array.prototype | ❌ | ✅ |
能用 map / reduce / join 等方法? | ❌ | ✅ |
验证一下:
function test() {
console.log(arguments instanceof Array); // false
console.log(Array.isArray(arguments)); // false
console.log(Object.prototype.toString.call(arguments)); // "[object Arguments]"
}
2.3 如何将 arguments 转为真数组?
有多种方式:
// ES6+ 推荐
const args = [...arguments];
// 或使用 Array.from
const args = Array.from(arguments);
// 传统方式(兼容性好)
const args = [].slice.call(arguments);
转换后即可使用所有数组方法:
function sum() {
const nums = [...arguments];
return nums.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
⚠️ 注意:箭头函数中没有
arguments!需使用剩余参数(...args)替代。
三、面试官想考察什么?
这两个问题看似简单,实则暗藏玄机:
new的实现 → 考察你对原型链、this 绑定、对象创建机制的理解;arguments的本质 → 考察你对数据类型、内置对象、ES 规范细节的掌握。
能清晰解释并手写代码,说明你不仅会用 API,更理解 JavaScript 的运行时模型。
四、总结与建议
| 知识点 | 关键理解 |
|---|---|
new 操作符 | 对象创建四步曲,原型链连接,this 绑定 |
arguments | 类数组 ≠ 数组,无数组方法,需转换 |
| 类数组对象 | 有 length + 索引属性,但不继承 Array.prototype |
| 实践建议 | 多手写核心机制(如 call/apply/bind/new),加深理解 |
🌟 结语
前端面试早已不是“会用框架”就能过关的时代。大厂更看重你对语言本质的理解。知其然,更要知其所以然。
下次当面试官问:“你能手写 new 吗?”——你可以自信地写出代码,并娓娓道来背后的原理。
真正的高手,不是记住答案的人,而是理解问题本质的人。