面试官:说说 new 的执行过程

本文为面试专题之JavaScript进阶------原理篇系列,new 的执行过程。

面经梳理见:2024年,龙年大吉吧。裁员,内卷,逆流而上,万字面经梳理

介绍

引用MDN的官方介绍,是这样定义 new 的:

new 运算符允许开发人员创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例

注:new 在JavaScript中是一个关键字。

语法

js 复制代码
new constructor
new constructor()
new constructor(arg1)
new constructor(arg1, arg2)
new constructor(arg1, arg2, /* ..., */ argN)
  • constructor:一个指定对象实例的类型的类或函数。
  • arg:一个用于被 constructor 调用的值列表。new Foonew Foo() 等价,换句话说:如果没有指定参数列表,则在不带参数的情况下调用 Foo。

用法与特点

举个栗子:

js 复制代码
function Parent(name) {
  this.name = name;
}
Parent.prototype.sayName = function () {
  return `我的名字是:${this.name}`
}

const son = new Parent("小帅");
console.log(son.name); // 访问构造函数里的属性
// 小帅

console.log(son.sayName()); // 访问原型里的属性
// 我的名字是:小帅
  1. 可以访问构造函数里的属性
  2. 可以访问原型上的属性

描述

当使用 new 关键字调用函数时,该函数将被用作构造函数。new 将执行以下操作:

  1. 创建一个空的 JavaScript 对象 obj
  2. objprototype 指向构造函数的 prototype 属性
  3. 使用给定参数执行构造函数,并将 obj 绑定为 this 的上下文(换句话说,在构造函数中的所有 this 引用都指向 obj
  4. 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象

实现

js 复制代码
function myNew() {
  // 1. 获取构造函数(参数对象里的第一个)
  const constructor = [...arguments][0]
  // 2. 创建对象
  const obj = Object.create(constructor.prototype)
  // 3. 执行传入构造函数,并修改 this
  const result = constructor.apply(obj, [...arguments].slice(1))
  // 4. 根据执行函数的返回值,判断是返回结果还是返回 obj 对象
  const isResult = (typeof result === 'object' && result !== null) || typeof result === "function"
  return isResult ? result : obj
}

或者你也可以这样写:

js 复制代码
function myNew(fn, ...args) {
  // 1. 获取构造函数
  const constructor = fn
  // 2. 创建对象 ,并指定原型
  const obj = Object.create(constructor.prototype)
  // 3. 执行传入构造函数,并修改 this
  const result = constructor.apply(obj, args)
  // 4. 根据执行函数的返回值,判断是返回结果还是返回 obj 对象
  const isResult = (typeof result === 'object' && result !== null) || typeof result === "function"
  return isResult ? result : obj
}

// 测试下,结果也是一致的
const son = myNew(Parent, "小帅");
console.log(son.name); // 访问构造函数里的属性
// 小帅

console.log(son.sayName()); // 访问原型里的属性
// 我的名字是:小帅

其中步骤 2 也可以这样写:

js 复制代码
// 1. __proto__
const obj = new Object()
obj.__proto__ = constructor.prototype

// 2. setPrototypeOf
// 指定原型链的终点null为其原型
const obj = Object.create(null) 
const propto = constructor.prototype
// setPrototypeOf方法可以把Object.create(null)指定null的创建强制修改原型
Object.setPrototypeOf(obj, propto) 

总结

简单来说,new 做的事情就是继承属性和方法,并改变this的上下文。

其实,通过手写 new 的实现,你应该可以发现,针对本文 new 的创建过程这个问题,仔细思考下...

我们完全可以把他看做是对原型链的一种考察,其中涉及的构造函数prototype__proto__Object.createObject.setPrototypeOf 等概念与方法,是不是又特别的熟悉呢?

其实,只要弄懂了JavaScript的原型与继承,也就明白了本文的内容了~

👀原型链的相关进阶文章请持续关注面试专栏的更新~

交流

好了,本文到此结束,欢迎来撩,一起学习🙋‍♂️~

面试相关的文章及代码demo,后续打算在这个仓库(JS-banana/interview: 面试不完全指北 (github.com))进行维护,欢迎✨star,提建议,一起进步~

相关推荐
我叫黑大帅6 分钟前
别再手动写 updated_at了,这坑我踩过
后端·面试·go
ShineWinsu19 分钟前
对于Linux:网络基础的解析
linux·网络·面试·udp·笔试·ip·tcp
咖啡星人k1 小时前
从Vibe Coding到Prompt Engineering:AI编程的新技能树
面试·职场和发展·ai编程
free352 小时前
作用域链与 Environment:变量查找、遮蔽和赋值怎么实现
javascript
YHL3 小时前
🤖 Agent 智能体开发实战 · 第一课:Tool Use —— 让大模型自动干活
前端·javascript·人工智能
HUMHSX4 小时前
Vue 组件通信核心知识点梳理
javascript·vue.js·ecmascript
风止何安啊4 小时前
🚦 前端并发请求 “交通管制”:别让你的接口堵成早高峰
前端·javascript·面试
熊猫钓鱼>_>5 小时前
2026 前端的三场底层革命:当 Vue、React Native 和 Three.js 同时去掉中间层
前端·javascript·vue.js·react native·架构·webgl·three.js
Fox爱分享5 小时前
字节二面:1000瓶酒,有一瓶是毒药,多少只老鼠可以查出来?
算法·面试·程序员
名字还没想好☜5 小时前
React useEffect 依赖数组踩坑:闭包陷阱与清理函数
前端·javascript·react.js·react·useeffect