JavaScript - new运算符

一. new运算符调用构造函数经历了4个步骤

  1. 创建一个空对象
  2. 将构造函数的作用域赋给新对象(修改this指向)
  3. 执行构造函数
  4. 如果构造函数没有显式返回对象,那么返回创建的新对象。

二. 假如构造函数显式的添加返回值会怎样?

  • 显式返回值不是对象的情况
function Person(name){
    this.name = name;
    return 'hello world';
}

let p = new Person('tom');
console.log(p);// Person { name: 'tom' }

正常的返回了预料之中的结果,也就是忽略了显式的返回值。

  • 显式返回值值是一个对象的情况
function Person(name){
    this.name = name;
    return {};
}

let p = new Person('tom');
console.log(p);// {}

这里说的对象并不是单单指{}这种对象,而是指对象类型,数组[]也是一样的。

function Person(name){
    this.name = name;
    return [1,2];
}

let p = new Person('tom');
console.log(p);// [ 1, 2 ]

得到的并不是新的Person实例,而是显式返回的空对象。

  • 经过进一步的测试发现:
    构造函数返回值为所有基本数据类型时(Boolean、Number、Null、String、Symbol、Undefined),返回的都是创建的对象
    构造函数返回值为函数时,返回函数
function Person(name){
    this.name = name;
    return function a(){

    };
}

let p = new Person('tom');
console.log(p);// [Function: a]

构造函数返回值为其他对象类型时(Array等),返回该对象

三. 如何模拟一个new操作符(new Foo())

  1. new创建的对象是继承自Foo.prototype
  2. 需要修改this指向
  3. 判断Foo有没有返回值,或者说返回值是什么类型的。
  4. 如果返回值类型为基本数据类型,返回创建的对象。如果返回值为Function,返回这个函数。如果返回值为其他对象类型,返回该对象。
  • 使用Object.create()修改原型关系
let new2 = function(fn,...args){

    // 使用Object.create()实现继承
    let obj = Object.create(fn.prototype);

    // 执行构造函数,并修改this
    let res = fn.apply(obj,args);

    // 判断返回值
    if(typeof fn() !== 'object' && typeof fn() !== 'function'){
       return obj;
    }else{
        return res;
    }
}
  • 直接通过修改__proto__链接到原型,不太优雅
let new2 = function(fn,...args){

    // 链接到原型
    let obj = {};
    obj.__proto__ = fn.prototype;

    // 执行构造函数,并修改this
    let res = fn.apply(obj,args);

    // 判断返回值
    if(typeof fn() !== 'object' && typeof fn() !== 'function'){
       return obj;
    }else{
        return res;
    }
}
  • 测试
function Person(name,age){
    this.name = name;
    this.age = age;
}
let p = new2(Person,'tom',21);
console.log(p);// Person { name: 'tom', age: 21 }
console.log(p.constructor);// [Function: Person]
console.log(p instanceof Person);// true

你可能感兴趣的:(JavaScript - new运算符)