每日一题(三三)实现 new 运算符

实现 new 运算符的方法

解析:

要实现 new 运算符的方法,首先要明白使用 new 来调用函数,或者说发生构造函数调用时,会执行哪些操作:

  1. 创建(或者说构造)一个全新的对象
  2. 这个新对象会被执行 [[prototype]] 连接
  3. 这个新对象会绑定到函数调用的 this
  4. 执行这个函数里面的语句
  5. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象

代码:

function _new(){
    //1.拿到传入参数中的第一个参数,即构造函数名 Func
    var Func = [].shift.call(arguments);

    //2.创建一个空对象obj,并让其的隐式原型__proto__ 指向 构造函数的显式原型 Func.prototype
    var obj = Object.create(Func.prototype);
    
    //第二步也可以用以下方式:
    //var obj = {};
    //obj.__proto__ = Func.prototype;

    //3.执行构造函数,并将 this 指向新创建的空对象 obj
    var ret = Func.apply(obj,arguments);

    //4.如果构造函数的返回值是对象则直接返回,否则返回新创建的对象 obj
    return typeof ret === 'object' ? ret : obj;
}


//测试
function Person(name,age){
     this.name = name;
     this.age = age;
}


var p1 = _new(Person,'LL',18);
console.log(p1);

//结果如下:

Person {name: "LL", age: 18}
name: "LL"
age: 18
__proto__:
constructor: ƒ Person(name,age)
length: 2
name: "Person"
arguments: null
caller: null
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: VM258:21
[[Scopes]]: Scopes[1]
__proto__: Object

Obect.create()方法创建一个新对象,使用现有对象来提供新对象的__proto__。

如何理解 [].shift.call(arguments)

因为 shift 内部实现是使用的 this 代表调用对象,那么当 [].shift.call() 传入 arguments 对象的时候,通过 call 函数改变原来的 shift 方法的 this 指向,使其指向 arguments ,并对 arguments 进行复制操作,而后返回一个新数组。至此便完成了 arguments 类数组转为数组的目的,其实这可以理解为,让类数组调用数组的方法。

也可以写成 Array.prorotype.shift.call(arguments);当然可以直接使用 es 6 的扩展运算符 [...arguments] 或者 Array.from(arguments) 直接将其转化为数组再进行操作。

猜你喜欢

转载自blog.csdn.net/MFWSCQ/article/details/106134901