JavaScript - new运算符

2019-10-20  本文已影响0人  ElricTang

一. 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实例,而是显式返回的空对象。

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,返回这个函数。如果返回值为其他对象类型,返回该对象。
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;
    }
}
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
上一篇 下一篇

猜你喜欢

热点阅读