• Javascript 闭包与高阶函数 ( 二 )


    在上一篇 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

  • 相关阅读:
    线性判别分析(Linear Discriminant Analysis, LDA)算法分析
    OpenCV学习(37) 人脸识别(2)
    OpenCV学习(36) 人脸识别(1)
    OpenCV学习(35) OpenCV中的PCA算法
    PCA的数学原理
    OpenCV学习(34) 点到轮廓的距离
    OpenCV学习(33) 轮廓的特征矩Moment
    OpenCV学习(32) 求轮廓的包围盒
    http://www.cnblogs.com/snake-hand/p/3206655.html
    C++11 lambda 表达式解析
  • 原文地址:https://www.cnblogs.com/likeFlyingFish/p/6426892.html
Copyright © 2020-2023  润新知