【JS】手撕操作符new(保证你理解&面试满分回答

我们平时在 JavaScript 中使用构造函数创建对象时,都会用到 new 关键字。但很多八股一上来就抛出“new 的四个步骤”,看着很标准,但也很抽象。到底 new 做了什么?怎么一步步执行的?我们用代码来复现整个过程

new做了什么

1. 创建一个空对象

我们先来从最基本的开始,定义一个构造函数 foo,然后用 new 关键字来调用它

    function foo(){
    }
    console.log(new foo);

看看控制台输出了什么

在这里插入图片描述

到这一步我们确认:使用 new 调用构造函数,最基本的效果就是创建了一个空对象

2. 将空对象的原型,指向于构造函数的原型

这一步是让我们创建的对象能够“继承”构造函数原型上的方法和属性。我们可以通过对比 __proto__ 来验证这一点

    console.log(foo.prototype == new foo().__proto__)
    // 构造函数的原型 == 空对象的原型
    // true

控制台输出为true

3. 将空对象作为构造函数的上下文(改变this指向

如果你直接调用构造函数,不加 newthis 默认会指向全局对象(非严格模式下是 window

    function foo() {
      console.log(this); // 全局状态下指向window
      this.name = "张三"; // undefined
    }
    console.log(foo());

控制台输出:
在这里插入图片描述

添加new关键字后,

console.log(new foo());

控制台输出:
在这里插入图片描述

this指向改变了。所以使用 new,就是为了让 this 正确地指向我们新建的对象

4. 对构造函数有返回值的处理判断

当构造函数返回的是引用类型(对象或函数)时,返回这个值;若返回的是原始类型(例如数字、字符串、null、undefined),则忽略,返回新建对象

可以写成

return (result !== null && (typeof result === 'object' || typeof result === 'function')) ? result : obj;

手动实现new

理解了上述四步之后,我们就可以自己手写一个 _new 方法,模拟 new 关键字的全部行为。下面是完整代码:

function _new(fn, ...args) {
      // 1. 创建了一个空对象
      const obj = {}; // 或 var obj = Object.create({});

      // 2. 将空对象的原型,指向构造函数的原型
      Object.setPrototypeOf(obj, fn.prototype);

      // 3. 将空对象作为构造函数的上下文(改变this指向
      const result = fn.apply(obj, args);

      // 4. 对构造函数有返回值的处理判断
      return result instanceof Object ? result : obj;
    }

测试一下

function Person(age, name) {
      this.age = age;
      this.name = name;
    }
console.log(_new(Person, 18, "张三"));

控制台输出:

在这里插入图片描述

成功创建

注:如果不熟悉.apply()或.setPrototypeOf()的去看一下官方文档

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf

面试怎么答

首先,创建一个新对象,并为其设置原型链,将对象的 [[Prototype]] 指向构造函数的 prototype,使其能够访问原型链上的方法和属性 ;再让构造函数在新对象上执行,此时 this 指向新对象;最后判断返回值,如果构造函数返回一个对象,则直接返回它;否则返回新对象

建议不止停留在八股文记忆层面,而是用浏览器、调试器一步步验证、实现,哪怕是造个轮子,也比背一百遍更有效

参考

https://www.bilibili.com/video/BV1FF411H7ig/?spm_id_from=333.337.search-card.all.click&vd_source=25de877a1d1cc18eac3e3d919f023f70

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/new

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值