JS闭包

作者: seafruit | 来源:发表于2016-09-18 20:58 被阅读0次

数学中的闭包与JS闭包

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

数学上,闭包是指一个集合在某个运算下闭合,也就是对该集合进行某种运算,得到的结果仍属于该集合。
在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的值,但在函数外部却无法正常访问函数内部定义的变量。

  • 作用域链:
    看个例子,摘自CSDN的博客(Skycrab)
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);
};
···
  • with语句。with语句主要用来临时扩展作用域链,将语句中的对象添加到作用域的头部。
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是匿名函数且是全局变量,它本身也是一个闭包,在函数外部对函数内部的局部变量进行操作。

一些例子:

  • (1)
var name = "name";
var people = {
    name : "peopleName",
    getName : function(){
        return function(){
            return this.name;
        };
    }
};
alert(people.getName()());//The Window
  • (2)
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
  • (3)
function outerFun()
{
    var a =0;
    alert(a);
}
var a=4;
outerFun();
alert(a);

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

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

结果为0,0

闭包的缺点:

不必要的闭包会徒增内存消耗!

相关文章

  • php之闭包函数(Closure)

    php闭包函数(Closure) JS闭包 js和php闭包使用和区别

  • JS闭包

    JS闭包 闭包练习

  • JS闭包问题(二)

    在之前的JS闭包问题(一)文章中大概介绍了一下JS闭包,同时讲了闭包与变量之间的问题,今天我们继续聊闭包,聊聊闭包...

  • JS闭包大结局(JS闭包系列3)

    在上一篇中再谈JS闭包(JS闭包系列2),我详细的介绍了JS中的变量作用域相关的概念,结合第一节关于JS闭包(JS...

  • JS闭包入门

    最近有看到朋友的面经里提到的JS闭包的问题,就想研究研究,以下是我对JS闭包的简单理解。 到底什么是JS闭包? 定...

  • 学习JavaScript闭包和作用域笔记

    JS JavaScript闭包和作用域 闭包 JavaScript高级程序设计中对闭包的定义:闭包是指有权访问另外...

  • 再谈JS闭包(JS闭包系列2)

    这篇文章,来继续谈谈Javascript闭包的剩余问题。因为在上一篇文章中关于JS闭包(JS闭包系列1)主要简单的...

  • 简单的聊一下闭包

    js中的闭包 闭包是学习js中永远也绕不过去的一个坎,那么,今天我们就去一段简单的代码开始聊一聊闭包 什么是闭包 ...

  • 浅谈闭包

    js中的闭包 闭包是学习js中永远也绕不过去的一个坎,那么,今天我们就去一段简单的代码开始聊一聊闭包 什么是闭包 ...

  • 闭包??

    什么闭包,闭包有什么用?http://js.jirengu.com/pogadikofa/1/闭包是在某个作用域内...

网友评论

      本文标题:JS闭包

      本文链接:https://www.haomeiwen.com/subject/hqegettx.html