手写New


title: 手写New
date: 2022-09-14 16:38:38
tags:

  • js
    categories:
  • JS

手写new

new的过程

要了解new,肯定要知道原生new都在‘后台’执行了哪些操作。

  1. 在内存中创建一个新的空对象
  2. 将这个对象的__proto__指向构造函数的prototype原型对象
  3. 将构造函数的作用域赋给这个对象(就是改变构造函数的this指向这个新的对象)
  4. 执行构造函数内部的代码,并将其属性和方法添加给那个新的对象
  5. 返回这个新的对象

编写

new示范

要写一个new就要先看看new是怎么使用的

function Person(name,age) {
    this.name = name;
    this.age = age;
}
Person.prototype.sayHi = function(){
    console.log('Hello world!');
}

let myPerson = new Person('张三',19);
myPerson.sayHi(); // Hello world
console.log(myPerson); // Person {name: '张三', age: 19}

自制

按照原生new的流程一步一步的书写就可以实现

function myNew(Con,...args) {
    // 1.在内存中创建一个空对象
    let obj = {};
    
    // 2.将新对象的原型指针指向构造函数的原型属性
    obj.__proto__ = Con.prototype;
    
    // 3.构造函数内部的this被赋值为这个新对象(即this指向新对象)
    // 4.执行构造函数内部的代码(给新对象添加属性)
    let res = Con.apply(obj,args);// apply会执行Con函数,当然此时的this已经是obj了
    
    // 5.如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象
    if (res instanceof Object) {
        return res
    }else{
        return obj
    }
}

注意

let res = Con.apply(obj,args);

这一部分是改变传入构造函数的this指向为创建的空对象。而第二个参数是要传递给那个构造函数的。apply方法是会执行一次Con的,所以你传入的args就传递给了那个构造函数,当然你的构造函数里面写的无非就是this.xxx = xxx这种…

如果传入的构造函数有返回值,那么就要返回那个返回的值,前提是返回的是非空对象。都不满足则返回创建的新对象

使用

function Person(name,age) {
    this.name = name;
    this.age = age;
}
Person.prototype.sayHi = function(){
    console.log('Hello world!');
}
let myPerson = myNew(Person,'张三',19)
myPerson.sayHi();  // Hello world
console.log(myPerson);  // Person {name: '张三', age: 19}
<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、付费专栏及课程。

余额充值