Javascript 为什么for循环比Array.prototype.map()快

Javascript 为什么for循环比Array.prototype.map()快,javascript,Javascript,根据我在这里阅读的内容以及使用console.time()进行的个人测试,JavaScript中常规的for循环比使用Array.prototype.map()更快。为什么会这样?我假设您的简单for循环如下所示: var num = []; for (var i = 0; i < 100; ++i) num.push(i); var result = []; for (var i = 0; i < 100; ++i) result.push(Math.sqrt(num[i]

根据我在这里阅读的内容以及使用
console.time()
进行的个人测试,JavaScript中常规的
for
循环比使用
Array.prototype.map()
更快。为什么会这样?

我假设您的简单for循环如下所示:

var num = [];
for (var i = 0; i < 100; ++i)
  num.push(i);
var result = [];
for (var i = 0; i < 100; ++i)
  result.push(Math.sqrt(num[i]));
var num=[];
对于(变量i=0;i<100;++i)
推数(i);
var结果=[];
对于(变量i=0;i<100;++i)
结果推送(数学sqrt(num[i]);
这是非常直接和简单的。现在让我们看一看符合要求的EMCA-262:

取自spidermonkey

/*ES5 15.4.4.19*/
函数数组映射(callbackfn/*,thisArg*/){
/*第一步*/
var O=对象(本);
/*步骤2-3*/
var len=至_UINT32(O.长度);
/*第四步*/
if(arguments.length==0)
投掷者(JSMSG_MISSING_FUN_ARG,0,'Array.prototype.map');
如果(!IsCallable(callbackfn))
ThrowError(JSMSG_NOT_函数,反编译参数(0,callbackfn));
/*第五步*/
var T=arguments.length>1?参数[1]:无效0;
/*第六步*/
var A=新登斯雷(len);
/*步骤7-8*/
/*步骤a(隐式)和d*/
对于(var k=0;k

你能理解为什么
map
较慢吗?

因为函数调用很昂贵。示例代码?因为初始化一个新的作用域比不初始化一个新的作用域更昂贵?考虑<代码>函数()({控制台)日志(“Foo”);foo()
console.log('foo')。你认为哪一个要求口译员做“更少的工作”?答案很好,未来我将直接寻找函数的实现。
/* ES5 15.4.4.19. */
function ArrayMap(callbackfn/*, thisArg*/) {
    /* Step 1. */
    var O = ToObject(this);

    /* Step 2-3. */
    var len = TO_UINT32(O.length);

    /* Step 4. */
    if (arguments.length === 0)
        ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.map');
    if (!IsCallable(callbackfn))
        ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));

    /* Step 5. */
    var T = arguments.length > 1 ? arguments[1] : void 0;

    /* Step 6. */
    var A = NewDenseArray(len);

    /* Step 7-8. */
    /* Step a (implicit), and d. */
    for (var k = 0; k < len; k++) {
        /* Step b */
        if (k in O) {
            /* Step c.i-iii. */
            var mappedValue = callFunction(callbackfn, T, O[k], k, O);
            // UnsafePutElements doesn't invoke setters, so we can use it here.
            UnsafePutElements(A, k, mappedValue);
        }
    }

    /* Step 9. */
    return A;
}