您的位置:首页 > Web前端 > JavaScript

Javascript 闭包与高阶函数 ( 二 )

2017-02-21 23:14 676 查看
在上一篇 Javascript 闭包与高阶函数 ( 一 )中介绍了两个闭包的作用。 两位大佬留言指点,下来我会再研究闭包的实现原理和Javascript 函数式编程 。

今天接到头条 HR 的邮件,真是超级开心呐,希望熬过一个周后一切顺利 ~

这一篇,继续举一些闭包的常见例子 。

提取this

我们常常需要面临下面的业务场景

var push = Array.prototype.push;
var a = [];
push.call(a, 1);
console.log(a);   // 1

这样固然可行,可是 我们有时候更想进行下面的操作

var a = [];
push(a, 1);
console.log(a);   // 1

这应该怎么做呢? 思路就是将a 提取出来作为this,然后调用
Array.prototype.push
方法 。

Function.prototype.uncharrying = function() {
var self = this;

return function() {
var _this = Array.prototype.shift.call(arguments);
return self.apply(_this, arguments);
}
}

var push = Array.prototype.push.uncharrying();
var a = [];
push(a, 1);
console.log(a);




函数节流

在很多业务场景中,比如 window.onresize 或者一些轮播图组件中,为了防止不断触发,都会使用一个函数节流的操作。下面看一个最简单的函数节流

var flag = false;

window.resize = function(e){
if(flag) {
return;
}
setTimeout(function(){
... // 业务逻辑代码

flag = false;
},1000);
flag = true;
}

这样做可用,但是缺点很多 。

下面用一个闭包将其包装起来 。

window.resize = (function(e){
var flag = false;
return function(){
if(flag) {
return;
}
setTimeout(function(){
... // 业务逻辑代码

flag = false;
},1000);
flag = true;
}
})();

看起来更加优优雅一点 。如果把节流的函数单独剥离呢??下面是完整代码

var throttle = function ( fn, interval ) {

var __self = fn,    // 保存需要被延迟执行的函数引用
timer,      // 定时器
firstTime = true;    // 是否是第一次调用

return function () {
var args = arguments,
__me = this;

if ( firstTime ) {    // 如果是第一次调用,不需延迟执行
__self.apply(__me, args);
return firstTime = false;
}

if ( timer ) {    // 如果定时器还在,说明前一次延迟执行还没有完成
return false;
}

timer = setTimeout(function () {  // 延迟一段时间执行
clearTimeout(timer);
timer = null;
__self.apply(__me, args);

}, interval || 500 );
};

};

window.onresize = throttle(function(){
console.log( 1 );
}, 500 );

分时函数

与函数节流不同,分时函数用来限制函数调用的次数,用来提供页面性能 。

一个例子是创建 WebQQ的 QQ好友列表。列表中通常会有成百上千个好友,如果一个好友

用一个节点来表示,当我们在页面中渲染这个列表的时候,可能要一次性往页面中创建成百上千个节点。

在短时间内往页面中大量添加 DOM节点显然也会让浏览器吃不消,我们看到的结果往往就

是浏览器的卡顿甚至假死 。

这时候就需要分时函数,每隔一段时间运行一段 。

'use strict';

var timeChunk = function(argsAry, fn, count) {
var interval;
var exec = function() {
var l = argsAry.length;
for (var i = 0; i < Math.min(count || 1, l); i++) {
var arg = argsAry.shift();
fn(arg);
}
}

return function() {
interval = setInterval(function() {
var flag = exec();
if (argsAry.length === 0) {
clearInterval(interval);
interval = null;
}
}, 500)
}
};

var a = [],func;
for (var i = 0; i < 36; i++) {
a.push(i);
}

func = timeChunk(a, function(i) {
console.log(i);
}, 10)
func();




闭包和高阶函数的应用非常广泛,很多设计模式都是通过闭包和高阶函数来实现的 。

希望此文可以对你有帮助 。

转载请声明本文出处: http://www.cnblogs.com/likeFlyingFish/p/6426892.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: