我刚刚在jsperf:https://jsperf.com/mapping1
上运行了此基准测试我试图查看使用递归的地图是否可以击败Array.prototype
地图功能。我失去了。可怕的。有人可以解释原因吗?
map = function(f, xs) {
if (xs.length === 0) {return []}
return [f(head(xs))].concat(map(f, tail(xs)))
}
// head() and tail() do exactly what you would expect. I wish there was a way to programmatically fork lists in js...
答案 0 :(得分:1)
这是rapidMap的递归实现,但没有concat,它比map快20倍,只比原生Array.map慢1.5倍:
var Cx = function(){
this.map = function (f, xs) {
if (xs.length === 0) {return []}
return [f(head(xs))].concat(arguments.callee(f, tail(xs)))
}
this.fasterMap = function(f, xs, i) {
i = i || 0;
if (xs.length === 0 || i > xs.length - 1) {return []}
xs[i] = f(xs[i])
arguments.callee(f, xs, i + 1)
return xs
}
this.arrMap = function (f, xs) {
return xs.map(f)
}
}
function head(arr){return arr[0]}
function tail(arr){return arr.slice(1)}
function add1(x){return x + 1}
function rep(n,f){
for(var i = 0; i < n; i++)
f(i)
}
var cx = new Cx()
;[9,99,999].forEach(function(n){
var test = []
rep(n,function(i){test.push(i + 1)})
;['map','fasterMap','arrMap'].forEach(function(mapType){
var mapFn = function(){return cx[mapType](add1,test)}
if(n < 10)
console.log(' ' + mapType,mapFn())
else{
console.time(' ' + mapType + ' ' + n)
rep(1000,mapFn)
console.timeEnd(' ' + mapType + ' ' + n)
}
})
})
以下是Cloud9 IDE上的测试结果:
map [ 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
fasterMap [ 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
arrMap [ 3, 4, 5, 6, 7, 8, 9, 10, 11 ]
map 99: 45ms
fasterMap 99: 8ms
arrMap 99: 7ms
map 999: 2227ms
fasterMap 999: 102ms
arrMap 999: 85ms
所以答案是concat使你的地图功能变慢。