news 2026/3/1 9:40:08

手写系列:面试官问我 new 的原理,我直接甩出三个版本

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手写系列:面试官问我 new 的原理,我直接甩出三个版本

今天我们来聊聊 JavaScript 中那个既熟悉又神秘的 new 操作符。相信很多小伙伴在面试时都经历过这样的“名场面”:面试官微微一笑,推过来那个熟悉的键盘:“来,能不能手写一个 new 的实现?”

这时候,如果你只是背诵了代码,稍微问深一点可能就露怯了。今天,我们就把这个“黑盒”拆开,从底层原理到完美实现,彻底搞懂它!

一、核心原理拆解:new 到底干了啥?

我们在日常开发中,const person = new Person('Fog', 18) 写得飞起。但 new 背后到底发生了什么?

简单来说,new 就是一个**“生产车间”**。它拿着你的图纸(构造函数),给你造出一个实实在在的产品(实例对象)。

这个过程,标准流程只有四步(核心四步法):

  1. 建空房:创建一个全新的空对象 {}。
  2. 挂牌子:将这个空对象的原型链(proto)链接到构造函数的原型对象(prototype)上。(这步最关键,决定了你能用这一类的公共方法)。
  3. 搞装修:将构造函数内部的 this 指向这个新对象,并执行构造函数。(给对象添加属性,如 name, age)。
  4. 交钥匙:判断构造函数的返回值。如果构造函数自己返回了一个对象(或函数),那就以它为准;否则,默认返回我们在第一步创建的那个新对象。

二、面试官到底在考什么?

面试官让你手写 new,绝对不是为了看你默写代码。通过这寥寥几行代码,他在考察你以下四大内功:

  1. 原型链的理解:你知不知道实例和类是怎么关联起来的?
  2. this 指向机制:你懂不懂怎么用 call 或 apply 改变函数执行上下文?
  3. 函数参数处理:面对不定参数,你会用 arguments 还是 ...args?
  4. 边界情况处理:**这是高分点!**如果构造函数里写了 return,你的代码还能正常工作吗?

三、手写进阶之路

接下来,我们由浅入深,演示三个版本的实现。

V1.0 青铜版:ES5 经典写法

这是最基础的写法,也是很多老教材里的标准答案。我们需要处理 arguments 这个“伪数组”。

JavaScript

function Person(name, age) { this.name = name; this.age = age; } Person.prototype.sayName = function () { console.log(this.name); } // 核心实现 function objectFactory() { // 1. 创建一个空对象 var obj = new Object(); // 2. 获取构造函数 // arguments 是类数组,没有 shift 方法,我们借用数组原型的 shift // 这行代码有两个作用:取出第一个参数(Constructor),同时 arguments 里剩下的就是参数了 var Constructor = [].shift.call(arguments); // 3. 链接原型:让 obj 能访问 Person.prototype 上的属性 obj.__proto__ = Constructor.prototype; // 4. 绑定 this 并执行 // 使用 apply 将 remaining arguments 传进去 var result = Constructor.apply(obj, arguments); // 5. 返回值处理 // 这是一个常见的简易判断,但其实有漏洞(稍后在王者版揭晓) return typeof result === 'object' && result !== null ? result : obj; } // 测试 var awei = objectFactory(Person, '阿伟', 20); console.log(awei.name); // 阿伟 awei.sayName(); // 阿伟

重点解析:

  • 为什么用 [].shift.call(arguments)?
    arguments 是一个类数组对象(有 length,有索引,但没数组方法)。通过 call,我们强行让它借用了数组的 shift 方法,切掉并拿到了第一个参数(构造函数),剩下的正好传给 apply。

V2.0 黄金版:ES6 现代化写法

时代变了,我们有了更优雅的语法糖。proto虽然好用,但在生产环境中被视为非标准(尽管浏览器支持),性能也不如 Object.create。

JavaScript

// 使用 ...args 剩余参数,告别 arguments function objectFactory(Constructor, ...args) { // 1. & 2. 创建对象并直接链接原型 // Object.create(proto) 创建一个新对象,带着指定的原型,性能更好,更符合规范 const obj = Object.create(Constructor.prototype); // 3. 执行构造函数 const result = Constructor.apply(obj, args); // 4. 返回值处理 (依然沿用旧逻辑) return typeof result === 'object' && result !== null ? result : obj; }

重点解析:

  • Object.create 的优势:它直接创建一个已经连接好原型的对象,避免了创建后再修改proto指针带来的性能损耗(修改原型链在 V8 引擎中是非常昂贵的操作)。

V3.0 王者版:无懈可击的最终版

注意了!如果你能写出这个版本,面试官绝对会对你刮目相看。

在 V1 和 V2 中,我们对返回值的判断是 typeof result === 'object'。这有一个巨大的隐形漏洞
如果构造函数返回的是一个 function 呢?

在 JS 原生 new 中,如果构造函数返回函数,new 表达式的结果就是那个函数。但 typeof function 是 'function' 而不是 'object',之前的代码会错误地返回 obj 实例。

JavaScript

function objectFactory(Constructor, ...args) { // 0. 参数校验 (严谨性加分项) if (typeof Constructor !== 'function') { throw new TypeError('Constructor must be a function'); } // 1. 创建对象,链接原型 const obj = Object.create(Constructor.prototype); // 2. 绑定 this 执行 const result = Constructor.apply(obj, args); // 3. 完美的返回值处理(关键修正!) // 如果 result 是对象(非null) 或者 是函数,则返回 result // 否则返回新创建的 obj const isObject = typeof result === 'object' && result !== null; const isFunction = typeof result === 'function'; return (isObject || isFunction) ? result : obj; } // 验证特殊情况 function Factory() { return function() { console.log('I am a function'); }; } const test = objectFactory(Factory); console.log(typeof test); // "function" —— 逻辑正确!

四、总结

你看,所谓的“手写源码”,其实就是对基础知识的排列组合。

  1. 创建:Object.create
  2. 执行:Function.prototype.apply
  3. 判断:类型检测与逻辑运算

掌握了这三点,new 操作符对你来说就不再是黑盒。下次面试遇到,直接展示“王者版”,告诉面试官:我不止会写,我还知道为什么要这么写。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/26 4:54:27

底盘电控悬架cdc控制系统文档(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

底盘电控悬架cdc控制系统文档(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码包含: CDC控制规格说明书 CDC减震器逻辑调校文档 CVSAe算法标准文档 Hiertune调校文档 Pascalis和Curcuruto调校日志处理文档全套文档内容完整&…

作者头像 李华
网站建设 2026/2/27 10:08:56

风机和水轮机互补发电(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

风机和水轮机互补发电(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码,基于粒子群算法微电网能量管理,基于模糊控制器互补发电系统,基于遗传算法风光互补,风力发电系统矢量控制&a…

作者头像 李华
网站建设 2026/2/25 19:37:18

宏智树AI——AI5.0驱动,重新定义学术写作全流程智能解决方案

在人工智能深度赋能学术领域的今天,论文写作不再是“孤军奋战”的繁琐工程,一款专业、高效、合规的智能辅助工具,能让学术创作事半功倍。宏智树AI,作为由ChatGPT学术版模型驱动、搭载AI5.0技术架构的高端学术智能解决方案平台&…

作者头像 李华
网站建设 2026/2/27 9:04:07

量子化学中如何消除结构优化/过渡态计算产生的多余虚频?

对于初学者来说,量子化学计算中跑结构优化/过渡态的时候,经常会出现一些莫名其妙的小虚频让人十分头疼(一般对应取代基的旋转振动或是大分子的骨架振动)。本文旨在指导量化初学者应该如何处理这种情况。以过渡态计算为例1、将命令…

作者头像 李华
网站建设 2026/2/28 13:57:45

Rust 函数

Rust 函数 引言 在编程语言中,函数是执行特定任务的基本构建块。Rust 作为一种系统编程语言,其函数的概念与其它编程语言有所不同,尤其是在所有权(Ownership)和生命周期(Lifetime)方面。本文将深入探讨 Rust 函数的各个方面,包括其定义、使用、特性和最佳实践。 函数…

作者头像 李华
网站建设 2026/2/26 19:29:06

全国首个!医共体系统实现全栈国产化

在浙江建德,看病正悄悄变得不一样。 走进任何一家公立医疗机构,挂号、缴费、查报告——以往来回跑窗口的场景,正被一个码、一个平台、一套流畅的体验替代。而支撑这一切的,是一张完全由国产技术织就的“数字医疗网”。 覆盖浙江省…

作者头像 李华