手写new方法

本文介绍了一种手动实现JavaScript中new操作符的方法。通过自定义函数myNew,可以为新对象设置正确的原型,并调用构造函数来初始化属性。此外,还讨论了构造函数返回值的影响。

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

手写new方法

new方法大家一定不陌生,在创建一个对象时经常会使用new方法,今天我们试着自己封装一个new方法。

先拿出需要new的函数,也就是构造函数

function AA(name, age) {
	this.name = name
	this.age = age
}

分析:

  1. 创建出来的对象首先需要有构造函数里面的属性,也就是说我们应该执行构造函数,将值赋给新对象。这个时候就可以使用apply或者是call方法。(其实选择apply和call也是有讲究的。apply对于参数的书写无疑更加简单,但是他的内部其实也是执行了call方法,只不过增加了将数组参数拆开的过程,所以就性能而言,call永远比apply更快!)

2.其次除了属性之外,构造函数创建出来的实例,实例的原型应该指向的是构造函数的prototype属性。

3.当构造函数返回了一个引用类型,那new出来的数据就会是该引用类型(不包含函数),若不是,则返回创建的实例。
开始封装

function myNew(fn, ...arg) {
	if(typeof fn !== 'function') return
	let obj = Object.create(fn.prototype)
	let res = fn.call(obj, ...arg)
	return res instanceof Object ? res : obj 
}

就是如此简单!

注意这个方法不支持class形式

<think>嗯,用户想了解如何用JavaScript手动实现new关键字的功能。首先,我得回忆一下new关键字在JavaScript中的作用。当使用new调用构造函数时,它会创建一个新对象,并将这个对象的原型指向构造函数的prototype属性,然后执行构造函数,绑定this到新对象上,最后根据构造函数的返回值决定返回什么。 根据用户提供的引用资料,特别是引用[3]和[4],实现步骤大致分为几个步骤:创建空对象、设置原型、绑定this执行构造函数、处理返回值。引用[2]提到应该使用Object.create()来设置原型,而不是直接修改__proto__,因为后者在某些环境下可能不被支持或者严格模式下不允许。 首先,我需要创建一个新的空对象。然后,设置这个对象的原型为构造函数的prototype。这里可以用Object.create()方法,传入构造函数的prototype作为参数,这样新对象的原型链就正确了。接下来,需要将构造函数的this绑定到这个新对象,并执行构造函数。这里可以使用apply或者call方法,把新对象作为this的上下文传入,并传递参数。 执行完构造函数后,需要检查返回值。如果构造函数返回了一个对象或者函数,那么new操作符会返回这个对象,否则返回新创建的对象。这一步很重要,因为有时候构造函数可能自己返回一个实例,这时候需要优先使用这个返回值。 然后,用户提供的引用[4]中提到了两种方法,ES5和ES6的实现方式。ES5中使用的是手动设置__proto__属性,但根据引用[2],更推荐使用Object.create()。因此,在代码实现时应该采用更安全的方法,避免直接操作__proto__。 接下来,我需要将这些步骤转化为具体的函数。例如,函数myNew接收构造函数和参数,创建对象,设置原型,应用构造函数,处理返回值。在代码中,可能需要使用arguments对象来处理传入的参数,或者用剩余参数语法来简化。 测试用例也很重要,比如定义一个Person构造函数,然后使用手动实现的myNew来创建实例,检查实例的属性以及原型是否正确。同时,测试构造函数返回对象的情况,确保myNew正确处理这种情况。 需要注意的是,ES6的Reflect.construct方法也可以用来实现,但用户的问题可能更关注于手动实现,所以应该集中在传统的方法上。 最后,总结实现步骤,并比较手动实现与原生new的区别,比如原型链的处理和返回值的判断,确保用户理解其中的原理和注意事项。</think>### JavaScript手动实现new关键字的原理与方法 在JavaScript中,`new`关键字用于通过构造函数创建对象实例。其核心原理可分解为以下步骤: #### 一、实现步骤 1. **创建新对象** 创建一个空的普通对象`obj`,用于存储实例的属性和方法。 2. **设置原型链** 将`obj`的隐式原型(`__proto__`)指向构造函数的显式原型(`prototype`),实现继承。推荐使用`Object.create()`来避免直接操作`__proto__`[^2][^5]。 3. **绑定`this`并执行构造函数** 通过`apply()`或`call()`将构造函数的`this`指向新对象`obj`,并传入参数执行构造函数[^3][^4]。 4. **处理返回值** 若构造函数返回引用类型(对象/函数),则直接返回该值;否则返回新对象`obj`[^4]。 --- #### 二、代码实现(ES6推荐方式) ```javascript function myNew(Constructor, ...args) { // 1. 创建对象并设置原型 const obj = Object.create(Constructor.prototype); // 2. 执行构造函数并绑定this const result = Constructor.apply(obj, args); // 3. 处理返回值 return result instanceof Object ? result : obj; } ``` #### 三、示例验证 ```javascript function Person(name) { this.name = name; } Person.prototype.sayHi = function() { console.log(`Hi, I'm ${this.name}`); }; const p = myNew(Person, 'Alice'); p.sayHi(); // 输出: Hi, I'm Alice console.log(p instanceof Person); // true ``` --- #### 四、与原生`new`的差异 1. **原型链处理** 原生`new`通过内部机制直接关联原型,而手动实现需依赖`Object.create()`。 2. **返回值判断** 需严格检查构造函数返回值的类型,确保与原生的逻辑一致[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值