刚刚在jsperf中编写了一些测试用例,以便在使用Array.map
和其他替代方法时测试命名函数和匿名函数之间的区别.
http://jsperf.com/map-reduce-named-functions
(原谅网址名称,这里没有测试Array.reduce
,我在完全决定我要测试的内容之前命名了测试)
一个简单的for/while循环显然是最快的,我仍然感到惊讶的是,速度慢了10倍Array.map
......
然后我尝试了mozilla的polyfill https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Polyfill
Array.prototype.map = function(fun /*, thisArg */) { "use strict"; if (this === void 0 || this === null) throw new TypeError(); var t = Object(this); var len = t.length >>> 0; if (typeof fun !== "function") throw new TypeError(); var res = new Array(len); var thisArg = arguments.length >= 2 ? arguments[1] : void 0; for (var i = 0; i < len; i++) { // NOTE: Absolute correctness would demand Object.defineProperty // be used. But this method is fairly new, and failure is // possible only if Object.prototype or Array.prototype // has a property |i| (very unlikely), so use a less-correct // but more portable alternative. if (i in t) res[i] = fun.call(thisArg, t[i], i, t); } return res; };
然后我尝试了一个我自己编写的简单实现...
Array.prototype.map3 = function(callback /*, thisArg */) { 'use strict'; if (typeof callback !== 'function') { throw new TypeError(); } var thisArg = arguments.length >= 2 ? arguments[1] : void 0; for (var i = 0, len = this.length; i < len; i++) { this[i] = callback.call(thisArg, this[i], i, this); }; };
结果摘要:
从最快到最慢:
对于简单/ while(大约相同)
Map3(我自己的实现)
Map2(Mozilla polyfill)
Array.map
for in
意见
一个有趣的注意事项是,命名函数通常比使用匿名函数(大约5%)快得多.但是我注意到polyfill在firefox中的命名函数速度较慢,但在chrome中速度较快,但是chrome的自己的map实现在命名函数中较慢...我测试了这个函数大约10x,所以即使它不是完全密集测试(jsperf)已经这样做了,除非我的运气好,它应该足够作为指导.
此外,chrome的map
功能比我机器上的firefox慢2倍.根本没想到.
而且...... firefox自己的Array.map
实现比Mozilla Polyfill慢......哈哈
我不确定为什么ECMA-262规范声明map
可以用于阵列以外的对象(http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.19).这使整个地图功能慢3-4倍(如我的测试中所示),因为你需要检查每个循环的属性存在...
结论
如果您认为不同的浏览器执行方式略有不同,则命名和匿名函数之间没有太大区别.
在一天结束时,我们不应该真正微观优化,但我发现这很有趣:)