009-new实现原理

007-js创建对象的几种方法博客中,我们使用构造函数创建了对象,但是这里有个问题,new到底做了什么呢,导致构造函数模式工厂模式不一样呢。

我们借用《JavaScript高级程序设计》中的定义:要创建Person的新实例,必须使用new操作符,以这种方式调用构造函数实际上会经历以下4个步骤:

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

我们来用代码实现

1.实现第一步和第四步

由于new是关键字,所以我们使用myNew函数来模拟实现。

function myNew() {
    var o = new Object();
    return o;
}

是不是和工厂模式很像

2实现第二步和第三步

我们调用的时候要使用myNew(Person, 'James', 20)方式调用,所以我们要用arguments来取出函数中的参数

function myNew() {
    var o = new Object();  //  第一步:创建一个新对象
    var param = [].shift.call(arguments);  // 拿到第一个参数Person,也就是构造函数
    param.apply(o, arguments);  //  第二步:将构造函数的作用域赋给新对象(因此this就指向了这个新对象)和第三步:执行构造函数中的代码(为这个新对象添加属性)
    return o;  // 第四步:返回新对象
}

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function() {
        console.log(this.name);
    }
}


myNew(Person, 'James', 20).say();  // 'James'

这样我们已经按照步骤模拟实现了一个myNew方法,但是我们在原型上添加方法,就会报错了,加上以下代码尝试一下

Person.prototype.sayAge = function() {
    console.log(this.age);
}

myNew(Person, 'James', 20).sayAge();  // myNew(...).sayAge is not a function

所以,我们需要一个连接到原型的操作,由
008-JS原型和原型链(1)
的第四张图片可知,person.__proto__ === Person.prototype,所以最终实现版本是

function myNew() {
    var o = new Object();  //  第一步:创建一个新对象
    var param = [].shift.call(arguments);  // 拿到第一个参数Person,也就是构造函数
    // 新增代码
    //  o.__proto__ = param.prototype;
    Object.setPrototypeOf(o, param.prototype);  // 连接实例和原型,上面注释掉的方法效果跟这个一样
    param.apply(o, arguments);  //  第三步:将构造函数的作用域赋给新对象(因此this就指向了这个新对象)和第四步:执行构造函数中的代码(为这个新对象添加属性)
    return o;  // 第四步:返回新对象
}

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function() {
        console.log(this.name);
    }
}

Person.prototype.sayAge = function() {
    console.log(this.age);
}

myNew(Person, 'James', 20).say();  // 'James'
myNew(Person, 'James', 20).sayAge();  // 20

参考:
《JavaScript高级程序设计》
https://juejin.im/post/590a99015c497d005852cf26

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值