JavaScript的闭包

来源:互联网 发布:数据修炼系统下载 编辑:程序博客网 时间:2024/06/05 20:32

JavaScript闭包

闭包是指有权访问另一个函数作用域中的变量的函数

function compare(prop) {    return function (obj1, obj2) {        let val1 = obj1[prop];        let val2 = obj2[prop];        if (val1 < val2) return -1;        else if (val1 === val2) return 0;        else return 1;    };}var obj1 = {    age: 20,    name:'obj1'};var obj2 = {    age: 2,    name:'obj2'};var array = [obj1, obj2];array.sort(compare('age'));console.log(array); //[ { age: 2, name: 'obj2' }, { age: 20, name: 'obj1' } ]

我们在compare函数内部创建了一个匿名函数,由于匿名函数位于compare内部,所以可以访问compare的参数prop,这样就通过闭包访问了别的函数中的变量,延长了变量的生命周期。

需要注意的是,闭包保存的是所外层函数中的变量对象,而不是变量本身的值

function createFuncs() {    var res = [];    for (var i = 0; i < 10; i++) {        res[i] = function () {            return i;        };    }    return res;}console.log(createFuncs()[0]());//10console.log(createFuncs()[2]());//10console.log(createFuncs()[9]());//10

如上所示,如果想用这种方式保存每次循环中i的值是错误的做法。因为所创建的匿名函数的作用链中都保存着createFuncs函数的活动对象,所以他们每次引用的都是用一个变量i,即res中保存的函数中都只能返回i的最后一个值,10。

解决的这种问题的方法也很简单:

function createFuncs() {    var res = [];    for (var i = 0; i < 10; i++) {        res[i] = function (num) {            return function(){                return num;            };        }(i);    }    return res;}console.log(func()[0]());//0console.log(func()[2]());//2console.log(func()[9]());//9

如上所示,我们没有直接把闭包的值赋给数组,而是定义一个匿名函数接收即将返回的值,并执行它。我们知道JavaScript中函数参数是值传递的,所以传递给匿名函数的参数会被复制一个副本,并返回出来。

  • 模拟块级作用域

    由于JavaScript没有会计作用域的概念,这意味着只要是在函数内部,无论是否在语句块中生命的变量,出了语句块依然可以访问的到。

    function foo(){for(var i = 0; i < 10; i++){} console.log(i);//10}

    如上代码,出了for循环依然可以访问变量i

    由于JavaScript的最小作用域就是函数内部,所以我们可以借助匿名函数来模拟块级作用域。如下所示:

    function foo(){function(){  var i = 0 ;}console.log(i);//Unexpected token}