蝴蝶不菲
这个你需要通过阅读V8引擎的源代码来获取答案:function ArrayMap(f, receiver) { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.map"); // Pull out the length so that modifications to the length in the // loop will not affect the looping and side effects are visible. var array = TO_OBJECT(this); var length = TO_LENGTH(array.length); if (!IS_CALLABLE(f)) throw %make_type_error(kCalledNonCallable, f); var result = ArraySpeciesCreate(array, length); for (var i = 0; i < length; i++) { if (i in array) { var element = array[i]; %CreateDataProperty(result, i, %_Call(f, receiver, element, i, array)); } } return result;}在这里,我们注意到,它首先是用了一个TO_OBJECT来把数组转为了对象,然后用了一个for循环在对象中查找下标,也就是这一句话:if (i in array),而当我们用new Array(4)来创建数组时,实际创建的只是一个指针,并没有创建实体的4个元素,所以当它被转化为对象时,得到是{}这样的空对象,所以这里的每一个if语句分枝都不会被执行。但如果我们用var array = [null, null, null, null]或者哪怕array = [undefined, undefined, undefined, undefined]来做,效果都会大不一样,因为以这样方式创建的数组,转化为的对象是:{ 0: undefined, 1: undefined, 2: undefined, 3: undefined,}当对这样的对象进行if (i in array)操作时,可以找到相应的下标,所以可以依次执行。这就是根本原因。