面试官:说说 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,提建议,一起进步~

相关推荐
HEX9CF19 分钟前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
积水成江1 小时前
关于Generator,async 和 await的介绍
前端·javascript·vue.js
Z3r4y1 小时前
【Web】portswigger 服务端原型污染 labs 全解
javascript·web安全·nodejs·原型链污染·wp·portswigger
人生の三重奏1 小时前
前端——js补充
开发语言·前端·javascript
Tandy12356_1 小时前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
老华带你飞1 小时前
公寓管理系统|SprinBoot+vue夕阳红公寓管理系统(源码+数据库+文档)
java·前端·javascript·数据库·vue.js·spring boot·课程设计
小飞猪Jay1 小时前
面试速通宝典——10
linux·服务器·c++·面试
qbbmnnnnnn2 小时前
【WebGis开发 - Cesium】如何确保Cesium场景加载完毕
前端·javascript·vue.js·gis·cesium·webgis·三维可视化开发
数据分析螺丝钉2 小时前
力扣第240题“搜索二维矩阵 II”
经验分享·python·算法·leetcode·面试
无理 Java2 小时前
【技术详解】SpringMVC框架全面解析:从入门到精通(SpringMVC)
java·后端·spring·面试·mvc·框架·springmvc