参透 JavaScript —— 彻底理解 new 操作符及手写实现

前言

本篇文章主要理解 new 操作符的原理,并手写实现一个自己的 "new"

new 操作符在背后做了什么?

在上篇文章中讲解了原型与原型链,讲到了使用 new 操作符创建实例对象

  1. 为什么 new 操作符创建的对象会拥有构造函数上的全部属性和方法?
  2. 为什么实例对象上的原型指针会指向构造函数的原型?

要明白这些问题,就要知道 new 操作符在实例化时做了什么

翻开《JavaScript 高级程序设计》第四版中关于原型的篇章,当以 new 关键字调用函数时,会执行以下操作:

  1. 在内存中创建一个新对象
  2. 这个新对象内部的 [[Prototype]] 特性被赋值为构造函数的 prototyoe 属性
  3. 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)
  4. 执行构造函数内部的代码(给新对象添加属性)
  5. 如果构造函数返回非空对象,返回这个对象;否则,返回新创建的对象

手写自己的 new 操作符

按照上面流程,我们可以模拟写一个自己的 new

比如,我们拥有一个 myNew 函数

js 复制代码
function myNew(constructor, ...args) {
  // 1.在内存中创建一个新对象
  // 2.这个新对象内部的 `[[Prototype]]` 特性被赋值为构造函数的 prototyoe 属性
  const obj = Object.create(constructor.prototype);

  // 3. 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)
  // 4. 执行构造函数内部的代码(给新对象添加属性)
  const result = constructor.apply(obj, args);

  // 5. 如果构造函数返回非空对象,返回这个对象;否则,返回新创建的对象
  return (result !== null && typeof result === 'object') ? result : obj;
}

解析:

使用 Object.create 来实现第一步、第二步,这个方法会创建一个新对象,并且将新对象的原型指针指向传入的对象的原型

在第三步和第四步,使用了函数上的实例方法 Function.protytype.apply

这个方法会改变函数内部的 this 指向,并且将剩余的参数(arguments)作为数组传入,然后调用该函数

手写的效果

在谷歌浏览器 - F12 开发者工具上测试效果

总结

实例对象拥有构造函数的全部属性和方法,并且原型指针指向构造函数的原型,都是 new 操作符在背后做的工作:

  1. 在内存中创建一个新对象
  2. 这个新对象内部的 [[Prototype]] 特性被赋值为构造函数的 prototyoe 属性
  3. 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)
  4. 执行构造函数内部的代码(给新对象添加属性)
  5. 如果构造函数返回非空对象,返回这个对象;否则,返回新创建的对象

记住,手写实现 new 操作符,本质是为了实践理解 new 操作符的背后原理

参考资料

参透JavaScript系列

本文已收录至《参透 JavaScript 系列》,全文地址:我的 GitHub 博客 | 掘金专栏

交流讨论

对文章内容有任何疑问、建议,或发现有错误,欢迎交流和指正

相关推荐
沛沛rh451 小时前
React 学习笔记:State、hook —— 组件的记忆
前端·javascript·react.js
前端小L8 小时前
双指针专题(三):去重的艺术——「三数之和」
javascript·算法·双指针与滑动窗口
0和1的舞者8 小时前
Spring AOP详解(一)
java·开发语言·前端·spring·aop·面向切面
web小白成长日记9 小时前
在Vue样式中使用JavaScript 变量(CSS 变量注入)
前端·javascript·css·vue.js
QT 小鲜肉9 小时前
【Linux命令大全】001.文件管理之which命令(实操篇)
linux·运维·服务器·前端·chrome·笔记
C_心欲无痕9 小时前
react - useImperativeHandle让子组件“暴露方法”给父组件调用
前端·javascript·react.js
霖鸣10 小时前
Minecraft通过kubejs进行简单魔改
javascript
JackieDYH10 小时前
HTML+CSS+JavaScript实现图像对比滑块demo
javascript·css·html
BullSmall11 小时前
支持离线配置修改及删除操作的实现方案
前端
全栈前端老曹11 小时前
【前端路由】Vue Router 嵌套路由 - 配置父子级路由、命名视图、动态路径匹配
前端·javascript·vue.js·node.js·ecmascript·vue-router·前端路由