闭包总结:闭包的7种形式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了闭包总结:闭包的7种形式相关的知识,希望对你有一定的参考价值。

  根据闭包的定义,我们知道,无论通过何种手段,只要将内部函数传递到所在的词法作用域以外,它都会持有对原始作用域的引用,无论在何处执行这个函数都会使用闭包。接下来,本文将详细介绍闭包的7种形式。

返回值

  最常用的一种形式是函数作为返回值被返回:(返回N函数,所以外界保持对里的引用

var F = function(){
    var b = local;
    var N = function(){
        return b;
    }
    return N;
}
console.log(F()());

函数赋值

  一种变形的形式是将内部函数赋值给一个外部变量:(将F作用域里的函数N赋值给全局作用域的inner,所以F执行之后,inner保持了对F作用域里的引用

var inner;
var F = function(){
    var b = local;
    var N = function(){
        return b;
    };
    inner = N;
};
F();
console.log(inner());

函数参数

  闭包可以通过函数参数传递函数的形式来实现:(将F里的N作为参数给外界的Inner,F执行之后,外界Inner保持了对F里的引用

var Inner = function(fn){
    console.log(fn());
}
var F = function(){
    var b = local;
    var N = function(){
        return b;
    }
    Inner(N);
}
F();

IIFE

  由前面的示例代码可知,函数F()都是在声明后立即被调用,因此可以使用IIFE来替代。但是,要注意的是,这里的Inner()只能使用函数声明语句的形式,而不能使用函数表达式。

function Inner(fn){
    console.log(fn());
}

(function(){
    var b = local;
    var N = function(){
        return b;
    }
    Inner(N);
})();

循环赋值

  在闭包问题上,最常见的一个错误就是循环赋值的错误。

function foo(){
    var arr = [];
    for(var i = 0; i < 2; i++){
        arr[i] = function(){
            return i;
        }
    }
    return arr;
}
var bar = foo();
console.log(bar[0]());//2 

  正确的写法如下

function foo(){
    var arr = [];
    for(var i = 0; i < 2; i++){
        arr[i] = (function fn(j){
            return function test(){
                return j;
            }
        })(i);
    }
    return arr;
}
var bar = foo();
console.log(bar[0]());//0   

g(s)etter

  我们通过提供getter()和setter()函数来将要操作的变量保存在函数内部,防止其暴露在外部

var getValue,setValue;
(function(){
    var secret = 0;
    getValue = function(){
        return secret;
    }
    setValue = function(v){
        if(typeof v === number){
            secret = v;
        }
    }
})();
console.log(getValue());//0
setValue(1);
console.log(getValue());//1

迭代器

  我们经常使用闭包来实现一个累加器

var add = (function(){
    var counter = 0;
    return function(){
        return ++counter; 
    }
})();
console.log(add())//1
console.log(add())//2  

  类似地,使用闭包可以很方便的实现一个迭代器

function setup(x){
    var i = 0;
    return function(){
        return x[i++];
    }
}
var next = setup([a,b,c]);
console.log(next());//‘a‘
console.log(next());//‘b‘
console.log(next());//‘c‘

总结:

  关于这七种方式自己可以好好领会下。其实说到底就是作用域外界保持了对作用域里面的引用

以上是关于闭包总结:闭包的7种形式的主要内容,如果未能解决你的问题,请参考以下文章

Swift学习笔记——闭包的几种形式

前端学习(3331):闭包的形式7

JavaScript 闭包(随笔)

常见闭包形式

Swift初见Swift闭包

什么是闭包(closure),为什么要用它?在开发项目时什么地方用闭包?以及优点和缺点