Javascript 閉包與高階函數 ( 二 )

在上一篇 Javascript 閉包與高階函數 ( 一 )中介紹了兩個閉包的做用。 兩位大佬留言指點,下來我會再研究閉包的實現原理和Javascript 函數式編程 。javascript

今天接到頭條 HR 的郵件,真是超級開心吶,但願熬過一個周後一切順利 ~html

這一篇,繼續舉一些閉包的常見例子 。java

提取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;
}

這樣作可用,可是缺點不少 。
下面用一個閉包將其包裝起來 。app

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

相關文章
相關標籤/搜索