你不知道的 new

new关键字用于创建对象实例,它执行构造函数并绑定this到新对象。如果不使用new,构造函数的this将指向全局对象,可能导致未预期的结果。当构造函数返回一个非对象时,new仍返回新创建的对象。new的实现原理包括创建新对象,连接原型链,执行构造函数并根据返回值决定返回结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

🌈这篇文章探索 new 关键字,从以下几个方面介绍👇:

  • new 做了哪些操作?
  • new 返回不同的类型时会有什么表现?
  • new 的实现原理

new 做了哪些操作?

new 关键词的内部就是执行一个构造函数、返回一个实例对象,在 使用 new 的过程中,根据构造函数的情况,来确定是否可以接受参数的传递。下面我们通过一段代码来看一个简单的 new 的例子

function Person(){
   this.name = 'Tom';
}
var p = new Person(); 
console.log(p.name)  // Tom

⭐️这段代码比较容易理解,从输出结果可以看出,p 是一个通过 Person 这个构造函数生成的一个实例对象,这个应该很容易理解。

new 操作符可以帮助我们构建出一个实例,并且绑定上 this,内部执行步骤可大概分为以下几步:

  1. 创建一个新对象
  2. 对象连接到构造函数原型上,并绑定 this(this 指向新对象)
  3. 执行构造函数代码(为这个新对象添加属性)
  4. 返回新对象

new 返回不同的类型时会有什么表现?

在第四步返回新对象这边有一个情况会例外:

如果不用 new 这个关键词,结合上面的代码改造一下,去掉 new,会发生什么样的变化呢?我们再来看下面这段代码

function Person(){
  this.name = 'Tom';
}
var p = Person();
console.log(p) // undefined
console.log(name) // Tom
console.log(p.name) // 'name' of undefined
  • 从上面的代码中可以看到,我们没有使用 new 这个关键词,返回的结果就是 undefined。其中由于 JavaScript 代码在默认情况下 this 的指向是 window,那么 name 的输出结果就为 Jack,这是一种不存在 new 关键词的情况。
  • 那么当构造函数中有 return 一个对象的操作,结果又会是什么样子呢?我们再来看一段在上面的基础上改造过的代码。
function Person(){
   this.name = 'Tom'; 
   return {age: 18}
}
var p = new Person(); 
console.log(p)  // {age: 18}
console.log(p.name) // undefined
console.log(p.age) // 18

通过这段代码又可以看出,当构造函数最后 return 出来的是一个和 this 无关的对象时,new 命令会直接返回这个新对象,而不是通过 new 执行步骤生成的 this 对象

💪但是这里要求构造函数必须是返回一个对象,如果返回的不是对象,那么还是会按照 new 的实现步骤,返回新生成的对象。接下来还是在上面这段代码的基础之上稍微改动一下

function Person(){
   this.name = 'Tom'; 
   return 'Jerney';
}
var p = new Person(); 
console.log(p)  // {name: 'Tom'}
console.log(p.name) // Tom

👍可以看出,当构造函数中 return 的不是一个对象时,那么它还是会根据 new 关键词的执行逻辑,生成一个新的对象(绑定了最新 this),最后返回出来。

因此我们总结一下:new 关键词执行之后总是会返回一个对象,要么是实例对象,要么是 return 语句指定的对象

new 的实现原理

function create(fn, ...args) {
    if (typeof fn !== 'function') {
        throw 'fn must be a function';
    }
    // 1、用new Object() 的方式新建了一个对象obj
    // var obj = new Object()
    // 2、给该对象的__proto__赋值为fn.prototype,即设置原型链
    // obj.__proto__ = fn.prototype

    // 1、2步骤合并
    // 创建一个空对象,且这个空对象继承构造函数的 prototype 属性
    // 即实现 obj.__proto__ === constructor.prototype
    var obj = Object.create(fn.prototype);

    // 3、执行fn,并将obj作为内部this。使用 apply,改变构造函数 this 的指向到新建的对象,这样 obj 就可以访问到构造函数中的属性
    var res = fn.apply(obj, args);
    // 4、如果fn有返回值,则将其作为new操作返回内容,否则返回obj
    return res instanceof Object ? res : obj;
};
  • 使用 Object.create 将 obj 的proto指向为构造函数的原型;
  • 使用 apply 方法,将构造函数内的 this 指向为 obj;
  • 在 create 返回时,判断返回值类型决定返回结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值