深入理解new的原理与模拟实现

前面的话

new运算符的原理也是重点之一,这篇文章介绍new运算符。

定义

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

看一个例子:

function Person (name) {
    this.name = name;
}
Person.prototype.getName = function () {
    console.log( 'hello '+ this.name );
}
var person = new Person('wan');
person.name;// 访问构造函数里的属性 
// wan

person.getName();// 访问原型里的属性
// hello wan

可以看到new创建的实例有以下两个特性:

  • 访问构造函数里的属性
  • 访问到原型里的属性
模拟实现

下面来模拟实现 调用new的过程,细分为下面几个过程:

  • 新生成了一个对象
  • 获得构造函数
  • 链接到原型
  • 绑定 this,执行构造函数
  • 返回新对象
 function create() {
    // 创建一个空对象
    let obj = new Object();
    // 获得构造函数, arguments中去除第一个参数(第一个参数为构造函数)
    let Con = [].shift.call(arguments);
    // 链接到原型
    obj.__proto__ = Con.prototype;
    // 绑定this,执行构造函数
    let result = Con.apply(obj, arguments);
    // 优先返回构造函数返回的对象
    return typeof result === 'object' ? result : obj;
}

测试一下:

var person1 = create(Person, 'li');

person1.getName();// hello li

可以看到使用create函数创建的实例对象与new创建的实例对象功能一样。

这里注意的是,new 运算符优先返回的对象不是创建的空对象,而是构造函数返回的对象。

function Person2 (name, age) {
    this.name = name;
    return {
        age : age
    }
}

var person2 = new Person2('wan', 20);
console.log(person2.name);// undefined
console.log(person2.age);// 20

发现实例对象person2只能访问return语句返回的对象属性

所以在create函数的最后一步要检查构造函数返回的是否为一个对象,如果是则优先返回这个对象,否则返回创建的新对象

优先级

new运算符还要注意运算符优先级

function Foo() {
    return this;
}
Foo.getName = function () {
    console.log('1');
}
Foo.prototype.getName = function () {
    console.log('2');
}
new Foo.getName();// 1
new Foo().getName(); // 2

new Foo()的优先级大于new Foo,上面的运算可以看做:

    new ( Foo.getName());
    (new Foo()).getName();

对于第一个函数来说,先执行了 Foo.getName() ,所以结果为 1;

对于后者来说,先执行 new Foo() 产生了一个实例,然后通过原型链找到了 Foo 上的 getName 函数,所以结果为 2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值