为什么在实现new关键字的时候要说:“构造函数是第一个参数”

function myNew(){
  var obj = {}
  var constructorFunction = [].shift.call(arguments) // 拿到构造函数,因为构造函数是第一个参数,arguments里面的其余的参数就是构造函数的参数
  var params = arguments // 此时的arguments已经是去掉了第一个参数的arguments
  var res = constructorFunction.apply(obj, params) // 这句是改变constructorFunction的this指向到obj并且执行constructorFunction这个函数

  return res instanceof Object ? res : obj
}

代码第二行的,“构造函数是第一个参数”,使用new的时候,并没有把构造函数放在括号内进行传参吧?

阅读 2.7k
4 个回答
function MyClass(first, second) {
    this.first = first;
    this.second = second;
}

const myInst = myNew(MyClass, "hello", "world");
console.log(`${myInst.first} => ${myInst.second}`);

比如,通过 function 的形式定义了一个构造函数 MyClass(如果用 class 语法来定义,里面的 constructorFunction.apply 会报错),那么用 myNew 来生成对像就是 myNew(MyClass, 后面是构造参数)。上面的示例在 myNew 里的执行过程如下面注释

function myNew() {
    var obj = {}

    // 这里 constructorFunction 取到传入的 MyClass
    var constructorFunction = [].shift.call(arguments)

    // 由于上面的 shift 已经移除了第一个参数,即 MyClass
    // 这里 params 就是剩下的参数,即 ["hello", "world"]
    var params = arguments

    // 调用构造函数来生成对象,这里是把 `obj` 作为 `this` 传入的
    var res = constructorFunction.apply(obj, params)

    return res instanceof Object ? res : obj
}

从代码来看,应该是比较旧的 JavaScript 语法了,学习的时候可以用来理解 Function.prototype.applyFunction.prototype.call,以及生成对象的过程,但在实际开发中一般没多大用。实际开发建议使用 class 语法。

他的意思是,使用 myNew 的时候,第一个参数必须是构造函数

 [].shift.call(arguments) 
 // shift 已经把 arguments 的第一个拿掉了

@边城 大佬已经回答的非常好了。

你贴的代码是别人模拟实现new操作符的。
new其实是操作符。
模拟实现是用函数实现的。所以最后要调用,第一个参数要是构造函数。

myNew()

最后我贴下我的文章吧。

面试官问:能否模拟实现JS的new操作符

推荐问题
宣传栏