JS 中的 new() 执行了什么操作

本文详细介绍了JavaScript中new操作符的工作原理,包括创建新对象、设置原型链、执行构造函数及返回新对象的四个步骤。通过实例展示了如何手动实现new操作,并对比了ES5构造函数和ES6类的使用。此外,还提供了错误使用new时的解决方法,强调了rest参数在构造函数调用中的应用。
摘要由CSDN通过智能技术生成

要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4个步骤:

(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ;
(3) 执行构造函数中的代码(为这个新对象添加属性) ;
(4) 返回新对象。

new 操作符具体就干了三件事
//1. 生成一个空对象
var obj =  {};

//2. 将空对象的 __proto__ 成员指向 构造函数的 prototype (原型对象)
obj.__proto__ = Base.protype;

//3. 将构造函数的 this 指针替换成 obj
Base.call(obj);
常用的 new()
// new 的使用
// ES5构造函数
let Parent1 = function (name, age) {
    this.name = name;
    this.age = age;
};
Parent1.prototype.sayName = function () {
    console.log(this.name);
};
const child1 = new Parent1('一晌贪欢', 25);
child1.sayName() //'一晌贪欢'


//ES6 class类
class Parent2 {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    sayName() {
        console.log(this.name);
    }
};
const child2 = new Parent2('echo', 25);
child2.sayName() //echo

手动实现一个 new

// 手动实现 new
// 构造器函数
let Parent3 = function (name, age) {
    this.name = name;
    this.age = age;
};
Parent3.prototype.sayName = function () {
    console.log(this.name);
};
//自己定义的new方法
let newMethod = function (Parent3, ...rest) {
    // 1.以构造器的prototype属性为原型,创建新对象;
    let child3 = {};
    child3.__proto__ = Parent3.prototype;
    // let child3 = Object.create(Parent.prototype);
    // 2.将this和调用参数传给构造器执行
    Parent3.apply(child3, rest);
    // 3.返回第一步的对象
    return child3;
};
//创建实例,将构造函数Parent与形参作为参数传入
const child = newMethod(Parent3, 'ldh', 26);
child.sayName() //'ldh';

//最后检验,与使用new的效果相同
child instanceof Parent3//true
child.hasOwnProperty('name')//true
child.hasOwnProperty('age')//true
child.hasOwnProperty('sayName')//false

可以将

let child3 = {};
child3.__proto__ = Parent3.prototype;

用下面这替换,结果一致

let child3 = Object.create(Parent.prototype);
结果

运行结果

let myNew = function (Parent, ...rest){
    
    let child = {};
    child.__proto__ = Parent.prototype;

    //验证 rest 是否是数组
    // console.log(rest instanceof Array);//true 
    // Parent.call(child,rest);
    //rest 本身是参数数组,应当使用 apply
    Parent.apply(child,rest);  
    return child;

}

const child5 = myNew(Parent3,'jialei',66);
child5.sayName();

第一次写时,因为不熟悉 rest,用了call,输出结果打印的是整个对象,发现是call的问题,找到了rest的解释,改成apply就正确了。rest参数数组

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值