new操作符原理及实现

作者: 崔小叨 | 来源:发表于2019-09-25 09:24 被阅读0次

[toc]

分析:new做了什么

new操作符通过执行自定义构造函数或者js内置构造函数,从而生成一个实例对象。

mdn上把内部操作大概分为4步:

  1. 创建一个空的简单JavaScript对象(即{ } );
  2. 链接该对象(即设置该对象的构造函数)到另一个对象 ;
  3. 将步骤1新创建的对象作为this的上下文 ;
  4. 如果该函数没有返回对象,则返回this。

通过一个简单的demo感受下上面的步骤

function Person (name){
    this.name = name
}
let p = new Person('jack');
console.log(`p:`, p); // { name: 'jack' }
console.log(`p.__proto__===Person.prototype:`,p.__proto__===Person.prototype);  //true

可以看到new操作符执行Person构造函数后,返回了一个内部创建的新对象,并且以这个对象为上线文环境执行了一遍Person函数,最后将其返回,同时对象p的原型属性指向构造函数的原型,这样也就保证了实例能够访问在构造函数原型中定义的属性和方法

上面的demo中构造函数是没有返回值的,如果说构造函数有返回值呢,如下

function Person (name){
    this.name = name;
    return {age: 18}
}
let p = new Person('jack');
console.log(`p:`, p); // { age: 18 }

如果构造函数最后返回了一个对象,就会直接将其返回,而不是内部创建的新对象。

经过测试发现,除了返回对象,如果返回其他类型,只要最后返回的类型为引用类型object或者function(Function,Object,Array,Date,Error,Regexp,要排除null,因为typeof null === 'object')就会直接将其返回,而其他基本类型都会返回内部新创建的对象。

自定义实现

这里我们尝试通过封装一个myNew方法模拟new操作符的主要功能:接受若干参数,第一个参数为构造函数ctr,其余为构造器所需参数,myNew(ctr, arg1, arg2,...)

第一步

这里的第一步把mdn中的1、2步放在了一起:创建一个新对象,并将其__proto__属性指向构造函数的prototype属性

function myNew(ctr) {
    let obj = Object.create(ctr.prototype);
}

也可以使用如下方法

function myNew (ctr){
    let obj = {};
    obj.__proto__ = ctr.prototype;
}

第二步

获取到参数之后,以内部新创建的对象obj为上线文执行构造函数,作用是为obj赋值

function myNew(ctr) {
    let obj = Object.create(ctr.prototype);
    
    const args = [].slice.call(arguments, 1);
    let result = ctr.apply(obj, args);
    console.log(`obj:`,obj);
}

上面的const args = [].slice.call(arguments, 1);用于将arguments类数组转为数组并获取参数,也可以通过Array.form(arguments).slice(1)或者[...arguments].slice(1)实现。

第三步

对执行构造函数后的返回值result做兼容处理。
如果构造函数最终返回对象、函数、数组、日期等其他引用类型及Symbol,会将其直接返回,其他基本类型及nullundefined会返回内部新创建的对象实例。

function myNew(ctr) {
    let obj = Object.create(ctr.prototype);

    const args = [].slice.call(arguments, 1);
    let result = ctr.apply(obj, args);

    var isObj = (typeof result === 'object' && result !== null);
    var isFn = typeof result === 'function';
    return (isObj || isFn) ? result : obj;
}

测试

最后,简单测试一下
没有返回值

function Person(name) {
    this.name = name;
}
let p = myNew(Person,'jack');
console.log(`p:`,p);

有返回值

function Person(name) {
    this.name = name;
    return {age: 33}
}
let p = myNew(Person,'jack');
console.log(`p:`,p);

参考

面试官问:能否模拟实现JS的new操作符
手动实现一个new操作符理解

相关文章

  • new操作符原理及实现

    [toc] 分析:new做了什么 new操作符通过执行自定义构造函数或者js内置构造函数,从而生成一个实例对象。 ...

  • 第14题- new操作符内部实现原理

    面试题目: new 操作符内部实现原理是什么? 答案解析: new 操作符经常被用到,用面向对象语言们通用的观点来...

  • JS手动实现一个new操作

    要手动实现一个 new 操作符,首先要知道 new 操作符都做了什么事,即构造函数的内部原理:1.创建一个新对象;...

  • JS基础回归01:new操作符,原型和原型链

    本篇介绍 new 操作符的背后原理以及 JS 如何依赖原型形成原型链,完成继承。 new 操作符的本质 new 操...

  • 2021-06-19 new操作符的实现

    JavaScript中的new操作符的原理 例子 先定义了一个构造函数Person,然后通过new操作符生成Per...

  • new

    什么是new操作符 new会生成一个实例对象,该对象的this指向该实例 实现一个new操作符

  • new 原理及模拟实现

    定义 new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。 ——(来自于MDN) 举个栗...

  • 模拟call、apply和bind方法以及new操作符的实现

    在模拟实现 call、apply 和 bind 方法以及 new 操作符的过程中,能让我们更好的理解他们的运行原理...

  • new操作符

    最近在掘金上看到大佬 yck 的文章 重学 JS 系列:聊聊 new 操作符把new操作符的作用,如何自己实现ne...

  • JavaScript手写代码无敌秘籍

    1实现一个new操作符 new操作符做了以下事情: 1、创建了一个全新的对象2、会被执行[[Prototype]]...

网友评论

    本文标题:new操作符原理及实现

    本文链接:https://www.haomeiwen.com/subject/znsiuctx.html