分时函数
解决问题: 在渲染列表时,如果一次性渲染的列表数目过多,短时间添加大量 DOM节点会让浏览器吃不消,我们看到的结果往往是浏览器卡顿甚至假死
// arr 要被渲染到浏览器的数组
// fn 具体怎么生成到浏览器的方法
// count 每个时间段生成到浏览器的数目
// intervalTime 时间段间隔时间
var timeChunk = function (arr, fn, count, intervalTime) {
var obj, t;
var len = arr.length;
//在这里处理数据,每生成一个就从数组中去掉一个
var start = function () {
for (var i = 0; i < Math.min(count || i, len); i++) {
var obj = arr.shift(); //每添加一项就去掉一项
fn(obj); //执行插入方法
}
}
// 返回一个渲染数据的周期函数
return function () {
t = setInterval(function () {
if (arr.length == 0) {
return clearInterval(t) //插入完毕之后清除周期函数
}
start() //执行生成函数
}, intervalTime)
}
}
//生成要被渲染的数据列表
var arr = [], i = 1 ;
while (i<1001) {
arr.push(i);
i++
}
// 传入参数,获得数据渲染周期函数
var renderFriendList= timeChunk (arr, function (n) {
var div = document.createElement('div');
div.innerHTML = n;
document.body.appendChild(div)
}, 8, 200) //每200毫秒执行8次插入dom函数
// 执行渲染
renderFriendList()
思路:每指定时间内( intervalTime)生成指定数目的节点(count),这样就可以避免因短时间生成大量dom节点导致浏览器卡顿
函数柯里化
函数柯里化又叫函数求值,一个currying 函数接受到参数时并不会求值,而是返回另外一个函数。刚才传入的参数在函数形成的闭包中被保留下来。待到函数真正需要求值的时候,之前传入的参数都会被一次性求值。
// 这个函数用来存储传入的参数,传入参数时存储,不传入时进行计算
var currying = function (fn) {
var args = []; //传入的数据都被缓存在这里,在符合条件时一并传给计算函数
return function () {
if (arguments.length == 0) {
return fn.apply(this, args )
} else {
[].push.apply(args, arguments)
return arguments.callee // (这句可不要)返回自身,在后面可以这样用 cost(100)(200)
}
}
}
// 进行具体数据处理计算的方法
var cost = function(){
var money = 0 ;
for (var i = 0, l = arguments.length; i < l; i++) {
money += arguments[i]
}
return money
}
var cost = currying( cost );
cost( 100 );
cost( 100 );
cost( 100 );
console.log( cost() ) //300
函数节流
在某些场景下,函数有可能被非常频繁的调用,而造成一些比较大的性能问题。如:
- window.onresize事件
如果我们在window.onresize事件的函数里有一些跟DOM节点相关的操作,而跟DOM节点相关的操作往往会非常消耗性能,这时候浏览器就可能造成卡顿现象
2.mouse.move事件
如果我们给一个div绑定一个拖拽事件,也会频繁的触发该拖曳函数
3.上传进度
微云上传功能使用了一个浏览器插件,该插件在真正开始上传文件之前,会对文件进行扫描并随时通知javascript 函数,以便页面显示上传进度,但该插件通知频率极高,很显然,我们不需要这么频繁的去提示用户
总结来说就是,函数节流可以在我们不需要某些函数频繁触发时使用。
具体实现:
var throttle = function (fn, interval) {
var timer, firstTime = true;
return function () {
var args = arguments;
var _me = this;
if ( firstTime ) {
fn.apply(_me, args)
return firstTime = false;
}
if ( timer ) {
return false
}
timer = setTimeout(function () {
clearTimeout(timer);
timer=null;
fn.apply(_me, args)
}, interval || 500)
}
}
window.onresize = throttle (function () {
console.log(1)
}, 500)