在使用new调用构造函数时,不可能直接使用数组和apply(apply执行[[Call]]而不是[[Construct]])。但是,由于扩展语法,可以很容易地将数组与new一起使用。
var dateFields = [1970, 0, 1]; // 1 Jan 1970
var d = new Date(...dateFields);
为什么我们不能在构造函数中使用apply方法呢? call方法和construct方法有什么区别吗?
在使用new调用构造函数时,不可能直接使用数组和apply(apply执行[[Call]]而不是[[Construct]])。但是,由于扩展语法,可以很容易地将数组与new一起使用。
var dateFields = [1970, 0, 1]; // 1 Jan 1970
var d = new Date(...dateFields);
为什么我们不能在构造函数中使用apply方法呢? call方法和construct方法有什么区别吗?
构造函数通过this
访问构造的对象,您可以通过apply
的第一个参数轻松模拟它,因此[[Construct]]基本上只是具有不同上下文的[[Call]]:
var obj = Object.create(Date.prototype);
Date.apply(obj, dateFields);
var obj = Reflect.construct(Date, dateFields);
[[Call]]是通过Date(…)
调用的,而[[Construct]]是通过new Date(…)
调用的。如果你尝试使用new Date.apply(…, dateFields)
来[[Construct]]一个Date
,它实际上会在Function.prototype.apply
方法上调用[[Construct]],而不是Date
对象,这样并不能正确地初始化Date
对象,而是尝试初始化一个[[Prototype]]等于apply.prototype
的对象,因为apply()
不是一个可构造的函数,所以会抛出TypeError
。
需要澄清的是,我并不是说在ES5中不可能将参数数组应用于Date
构造函数,我只是解释为什么使用apply
来[[Construct]]一个Date
是行不通的。
Reflect.construct
吗? - Jonas Wilms