1.类数组快速转成数组
如arguments对象可以通过
let args = [].slice.call(arguments);
// or
let args = Array.prototype.slice.call(arguments);
args此时是真正的数组结构,可以调用数组对象拥有的方法。
2.apply处理arguments入参
当一个方法fn的入参是多个的时候,譬如:
function fn (arg1, arg2, arg3) {...}
fn(1, 2, 3);
// => function fn (arg1, arg2, arg3) {
// arg1 = 1;
// arg2 = 2;
// arg3 = 3;
// }
如果直接通过fn(arguments)调用,arguments=[1, 2, 3],则等价于fn([1,2,3])
function fn (arg1, arg2, arg3) {
arg1 = [1, 2, 3];
arg2 = undefined;
arg3 = undefined;
}
所以借用apply方法,fn.apply(this, arguments)可以把arguments的参数分别赋值给fn对应的入参中。
再比如一个求平均值的例子,如果有个求平均值函数average(...args)是可变参数:
average(1, 2, 3); // 2
average(1); // 1
average(4, 6); // 5
此时有个方法直接获取分数的数组:
var scores = getAllScores(); // [1, 2, 3]
要直接让aaverage调用scores数组,只需:
average.apply(null, scores);
3.柯里化的一个简单实现原理
函数柯里化是实现高阶函数的一个基础,一个简单的柯里化实现原理如下:
function func(fn) {
var args = [].slice.call(arguments, 1);
return function () {
var localArgs = [].slice.call(arguments);
return fn.apply(fn, args.concat(localArgs));
};
}
通过一个加法举个例子:
function add (a, b) {
return a+b;
}
var f = func(add, 2, 3); // 函数柯里化
console.log(f()); // 5
// 高阶函数的一般写法
var addTo = func(add, 2); // 函数柯里化
console.log(addTo(3)); // 5
4.巧用JS定时器,快速响应用户界面
研究表明,浏览器处理任务超过100ms则会对用户体验产生影响。因此结合JS定时器,把耗时较长的脚本拆分成较短的片段,让UI线程(Call Stack)得到及时更新。
对于处理一个大数组的时候,直接循环处理可能由于处理每个数组的内容比较耗时或者整个数组的数据太多导致耗时过长。
for(let i=0, len=items.length; i < len; i++) {
process(items[i]);
}
定时器取代循环必须考虑两个条件:
- 处理过程是否需要同步
- 数据是否按顺序处理
如果这两个条件都不需要满足的话,就可以用定时器分解任务达到优化的目的。
function processArray(items, process, callback) {
// 拷贝一份数组
let todo = items.concat();
setTimeout(function() {
// 处理时间时间小于50ms则持续执行
let start = +new Date();
do {
process(todo.shift());
} while (todo.length > 0 && (+new Date() - start < 50))
// 超过50ms时间则另设定时器执行
if (todo.length > 0) {
setTimeout(arguments.callee, 25);
} else {
// 处理完最后调用回调函数处理数组
callback(items);
}
}, 25)
}
var items = [...];
function outputValue(value) {
console.log(value);
}
processArray(items, outputValue, function(){
console.log("Done!");
});