closure 闭包

以下是学习笔记,来自阮一峰笔记

闭包是Javascript的一个难点,很多面试官都会问。。。
为了理解闭包必须先理解变量的作用域

一:变量的作用域

大体的分两类

  • 全局变量
  • 局部变量
    Javascript 这个语言的比较特殊的一点是函数可以获取外部的变量(全局变量),但外面无法获取函数内部的变量。

下面的函数可以获取函数外面的变量(局部变量)

var name = "Abd";
function say() {
  console.log(name);
}

say();   //abd

但下面的就不行了,也就是外面无法获取函数内的变量。

function say() {
  let name = "Abdcc";
}

say();
console.log(name); //error

另外注意一点是如果不定义let或war,则这个变量会变成全局的。

function say() {
  name = "Abdccfaa";
}

say();
console.log(name); //Abdccfaa

这样就不公平了,我们得想办法读取函数内部的变量啊(笑脸.png).

二:从外部读取内部变量

正常情况下我们做不到,因此我们得想出办法.我们想到的办法就是在函数内定义一个返回我们想要的变量的函数来获取函数内部的变量。

function say() {
  let n = 100;
  function bark() {
  let m=101;
    alert(n);
  }
  bark();
  console.log(m);    //m is not defined
}

say();

通过以上的函数我们就实现了获取say函数内部的变量。函数bark可以获取say函数内的所用变量,但反过来就不行,这是因为Javascript的语言特色决定的,子对象会一层一层的向上寻找父对象的变量,反着则不成立.(这个就很现实了,感觉闭包的函数就感觉是啃老族,拿父母亲的,但不会给他们回报(给他们自己的变量)).

既然我们可以通过函数(say)内部实现一个函数(bark)来获取say内部的变量,我们就可以通过返回bark来在say外部获取say内部的变量.

function say() {
  let n = 100;
  function bark() {
    alert(n);
  }

  return bark;
}

let result = say();
result();     // alerted the n 100

闭包的概念

上一个函数内bark就是闭包,简单来讲闭包就是会获取其他函数内部的变量的函数.因为Javascript中,只有函数内部的自函数才能可以读取局部变量,因此可以把闭包可以理解成定义在一个函数内部的函数,也就是用来跟父函数(在上面的例子的say函数)跟外面沟通的桥梁。
本质上是一座桥梁。

闭包的作用

主要有以下两处作用:

  • 上文提到的返回父函数内部的变量,起桥梁作用。
  • 让这些变量(父亲函数内部的变量)的值始终保存在内存中。
    通过以下例子来了解第二点作用。
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的值。f2(闭包)来返回f1内部的变量的值,然后result执行两次,第一次是999,第二次是1000.这证明了变量n一直保存在内存中,并没有因为f1调用后自动清楚。
原因是这样的,因为result是全局变量,因此得保存在内存中,因为result的保存依赖于f2,f2的保存依赖于f1,从而导致n一直保存在内存中。
这段代码另一个注意的地方是nAdd函数,nAdd是全局变量(没有加var等),也是个闭包,也是个匿名函数,所以nAdd是一个setter, 对f1的变量n做起改变。

使用闭包注意点

  • 闭包会使得函数中的变量都保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页性能问题。
  • 闭包在函数外部改变函数内部的变量的值,因此当函数是对象,把闭包当作它的公用方法,把变量当作私有变量,因此不能频繁改变函数内部的变量的值。
发布了83 篇原创文章 · 获赞 18 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/Abudula__/article/details/103353264
今日推荐