JavaScript中模拟 new 操作符的效果

本文探讨了JavaScript中的new操作符,详细解释了它在内存中创建新对象、链接原型链以及绑定this的过程。通过模拟实现new操作符,帮助读者更好地理解其工作原理。内容包括构造函数的执行流程、如何创建新对象并继承原型以及this的绑定规则。
摘要由CSDN通过智能技术生成
先导知识

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例 (MDN)

new 操作符做了什么?
  1. 在内存中创建一个新对象
  2. 这个对象会被执行 [[Protoype]] (也就是 _proto_) 链接
  3. 生成的新对象会绑定到函数调用的 this
  4. 通过 new创建的每个对象将最终被 [[Prototype]] 链接到这个函数的 prototype 对象上
  5. 如果函数没有返回对象类型 Object(包含 Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用会自动返回这个新的对象
模拟实现 (更好理解一点吧)

当代码 new Foo(...) 执行时,会发生以下事情:
a. 一个继承自 Foo.prototype 的新对象被创建。
b. 使用指定的参数调用构造函数 Foo ,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。
c. 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤 a 创建的对象。

Object.create() 方法创建一个新对象,使用现有的对象来提供新创建的对象的 __proto__
Object.create(null) 创建一个不继承任何原型的新对象

let o = {};
// 以字面量方式创建的空对象就相当于:
o = Object.create(Object.prototype)

new.target 属性允许你检测函数或构造方法是否是通过 new运算符被调用的
在通过 new运算符被初始化的函数或构造方法中,new.target 返回一个指向构造方法或函数的引用。在普通的函数调用中,new.target 的值是 undefined

let o = {};
o = Object.create(Object.prototype)

console.log(o._proto_) // undefined

/**
 * 模拟实现 new 操作符
 * @param  {Function} ctor [构造函数]
 * @return {Object|Function|Regex|Date|Error}      [返回结果]
 */
function newOperator(ctor) {
    if(typeof ctor !== 'function') {
        throw 'newOperator function the first params must be a function'
    }
    // ES6 new.target 是指向被 new 调用的构造函数
    newOperator.target = ctor
    
    // new 的 1、2、4 模拟 ,即创建新对象...
    const newObj = Object.create(ctor.prototype)

    // ES5 arguments 转成数组,当然也可以用 ES6 [...arguments], Aarry.from(arguments)
    // 除去 arguments 中的第一个参数
    const argsArr = [].slice.call(arguments, 1) // 等同于 [].shift.call(arguments)
    // new 的 3 模拟,新对象绑定到函数调用的 this
    // 获取 ctor 函数返回结果
    const ctorReturnResult = ctor.apply(newObj, argsArr)

    // Functoin, Array, Date, RegExg, Error 这些类型中合并起来只有 Object 和 Function 两种类型 typeof null 也是 'object' 所以要不等于 null,排除 null
    const isObject = typeof ctorReturnResult === 'object' && ctorReturnResult !== null
    const isFunction = typeof ctorReturnResult === 'function'
    if(isObject || isFunction){
        return ctorReturnResult;
    }

    // 模拟 new 5
    return newObj
}

// 验证
function Student(name, age) {
    this.name = name
    this.age = age
}
const student = newOperator(Student, '白醭飙尘', 24)
console.log(student) // Student {name: '白醭飙尘', age: 24}

const str = new String(123) // String {'123'}
console.log(str[1]) // 2
console.log(typeof str[1]) // string

参考:
面试官问:能否模拟实现JS的new操作符
深度解析 new 原理及模拟实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值