JS闭包

2016-09-18  本文已影响0人  seafruit

数学中的闭包与JS闭包

首先需要认识到一点,数学闭包和JS闭包是没有关系的。

数学上,闭包是指一个集合在某个运算下闭合,也就是对该集合进行某种运算,得到的结果仍属于该集合。
在JS中,百度百科援引官方的解释是:“闭包”指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。听起来有些难懂,那就让我们继续向下看吧。

闭包和什么有关系?

let n = 'Hello!' ;
function a(){
    var m = 'Bob.' ;//此处的var不能省略,如果省略,m就会变成全局变量。
    console.log(n) ;
}
a();//Hello!
console.log(m);//error

上面的例子中,n是全局变量,作用于全局;
m是局部变量,作用于函数a的内部;
在函数内部可以正常输出n的值,但在函数外部却无法正常访问函数内部定义的变量。

name="lwy";
function t(){
    varname="tlwy";
    functions(){
    varname="slwy";
    console.log(name);
    }
    functionss(){
    console.log(name);
    }
    s();
    ss();
}
t();

执行t()时,作用域链是:t()->window
执行s()时,作用域链是: s()->t()->window,所以name是”slwy";
执行ss()时,作用域链是: ss()->t()->window,所以name是”tlwy";

function createFunctions(){
    var result =newArray();
    for(var i=0; i < 10; i++){
        result[i] =function(){
        return i;
    };
}
return result;
}
var funcs = createFunctions();
for(var i=0; i < funcs.length; i++){
    console.log(funcs[i]());
}

输出10个10;WHY?
函数带()才是执行函数!
单纯的一句 var f = function() { alert('Hi'); }; 是不会弹窗的,后面接一句 f(); 才会执行函数内部的代码。类比上面的例子,也就是说,内部的函数在定义的时候就是在添加作用域链,循环的时候导致上级的i=10,然后在执行的时候,直接从顶级找到i,输出的自然就是10。
那怎么解决呢?

···
for(var i=0; i < 10; i++){
        function num(i){
            return function(){
                return i;  
        }
result[i] = num(i);
};
···
person={name:"yhb",age:22,height:175,wife:{name:"lwy",age:21}};
with(person.wife){
console.log(name);
}

with语句将person.wife添加到当前作用域链的头部,所以输出的就是:“lwy".
with语句结束后,作用域链恢复正常。

闭包如何解决外部访问内部的变量的问题?

function a(){
    var m = 'Bob.' ;
    function b(){
        console.log(m);
    }
    return b;
}
var A = a();
A();//Bob.

该例子中的b()就是闭包。从上面的例子中可以看出,我们将内部变量通过嵌套一个内部函数b,在b中进行操作最后将b返回出去。这样在外部就可以访问到内部的变量了。

闭包的作用一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中(因为a()内部的函数b()的执行要依赖a()中定义的变量)。

在“脚本之家”里面有一个特别好的例子,如下所示:

function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result();// 999
nAdd();
result();// 1000

result实际上是函数f2;
nAdd是匿名函数且是全局变量,它本身也是一个闭包,在函数外部对函数内部的局部变量进行操作。

一些例子:

var name = "name";
var people = {
    name : "peopleName",
    getName : function(){
        return function(){
            return this.name;
        };
    }
};
alert(people.getName()());//The Window
function outerFun()
{
    var a=0;
    function innerFun()
    {
        a++;
        alert(a);
    }
return innerFun;//注意这里
}
var obj=outerFun();
obj();//结果为1
obj();//结果为2
var obj2=outerFun();
obj2();//结果为1
obj2();//结果为2
function outerFun()
{
    var a =0;
    alert(a);
}
var a=4;
outerFun();
alert(a);

结果是0,4. 因为在函数内部使用了var关键字 维护a的作用域在outFun()内部.

function outerFun()
{
    //没有var
    a =0;
    alert(a);
}
var a=4;
outerFun();
alert(a);

结果为0,0

闭包的缺点:

不必要的闭包会徒增内存消耗!
上一篇 下一篇

猜你喜欢

热点阅读