🧪手写 new + arguments 转正指南:前端基础别再踩坑了!

7 阅读3分钟

“我不是对象,我是构造函数!”
“我不是数组,但我能遍历!”
—— JavaScript 里的两个“戏精”

如果你曾在面试中被问:“手写一个 new”,或者在控制台里对 arguments.reduce 报错一脸懵,那你不是一个人。今天我们就来揭开 JavaScript 中两场经典的 “身份冒充案”
👉 new 是如何“造人”的?
👉 arguments 为何总想混进数组圈?

准备好了吗?泡杯咖啡,我们边笑边学 ☕️


🔨 Part 1:手写 new —— 从“空对象”到“实例化”的魔法

你以为 new Person() 只是调了个函数?错!它背后上演了一出 四幕剧

  1. 出生:创建一个空对象 {}
  2. 认祖归宗:让这个对象的 __proto__ 指向 Person.prototype
  3. 灵魂注入:把 this 绑定到新对象,执行构造函数;
  4. 命运裁决:如果构造函数返回的是对象,就用它;否则,返回新对象。

于是,我们可以手写一个 myNew,还原这场“造人仪式”:

function myNew(Constructor, ...args) {
  // 1. 创建空对象,且继承构造函数的原型
  const obj = Object.create(Constructor.prototype);
  
  // 2. 执行构造函数,绑定 this
  const result = Constructor.apply(obj, args);
  
  // 3. 决定返回谁:构造函数返回的对象 or 新对象?
  return (result !== null && typeof result === 'object') ? result : obj;
}

✅ 测试一下:

function Person(name) { this.name = name; }
const p = myNew(Person, '掘金小张');
console.log(p.name); // "掘金小张" ✅

💡 冷知识new 其实不是关键字,而是一个运算符——但它干的活,比很多关键字还重!


🎭 Part 2:arguments —— 那个“长得像数组”的冒牌货

来看你写的这段经典代码(已激活):

function add() {
  let sum = 0;
  for (let i = 0; i < arguments.length; i++) {
    sum += arguments[i];
  }
  return sum;
}
console.log(add(1, 2, 3)); // 6

看起来没问题?但如果你尝试:

// ❌ TypeError: arguments.reduce is not a function
return arguments.reduce((a, b) => a + b, 0);

Boom!💥 因为 arguments 根本不是数组

它到底是什么?

  • 是一个 类数组对象(Array-like Object)
  • 有 length ✅
  • 能用 arguments[0] 访问 ✅
  • 但 没有 pushmapreduce 等数组方法 ❌

📸【表情包建议】
插入一张“我看起来像程序员,但我只是穿了格子衫”的梗图,配文:“我看起来像数组,但我只是有 length。”


🔄 如何帮 arguments “转正”?

别急,JS 社会很包容,给它三条“落户通道”:

方法代码特点
展开运算符[...arguments]✨现代、简洁、推荐
Array.fromArray.from(arguments)🧼语义清晰,可处理 iterable
老派 sliceArray.prototype.slice.call(arguments)🕰️兼容 IE,怀旧党最爱
function add(...args) { // 更推荐!直接用 rest 参数
  return args.reduce((a, b) => a + b, 0);
}

🎯 最佳实践:ES6 之后,请优先使用 剩余参数(...args
它生下来就是真·数组,不用再“整容”或“洗白”!


🤔 为什么这些“细节”值得你死磕?

场景价值
面试手写 new + arguments 区别 = 基础题满分
调试避免 arguments.map is not a function 这种低级报错
架构理解原型链 & 动态参数机制,写出更灵活的工具函数
装X在 Code Review 时说:“这里用 rest 参数更语义化” 😎

🎬 彩蛋:JS 的“身份哲学”

JavaScript 从来不是一个“非黑即白”的语言:

  • 函数是对象 ✅
  • 对象可以当函数调用(如果加了 [[Call]])✅
  • 数组是对象 ✅
  • null 的 typeof 是 "object"(历史 bug)😅

所以,arguments 想当数组,new 想造对象——
不是它们疯了,是 JS 本来就这么自由!


✅ 总结:记住这两句话

  • new 不是魔法,是四步流程;
  • arguments 不是数组,但你可以让它变成。

下次再有人问你:“JS 里最像数组又不是数组的是谁?”
你可以微微一笑:“是我,arguments,正在申请 Array 户口。” 👮‍♂️📄