首页 > 图灵资讯 > 技术篇>正文

Javascript之旅——第十站:为什么都说闭包难理解呢?

2023-04-21 10:01:47

  大多数研究过js的朋友会说,只要了解js的原型和封闭包,然后说这些都是js的高级内容,然后涉及到各种神马的作用领域。。。然后很多

人会在云雾中被忽悠。。。下面我也试着说说闭包,看看我说的是不是简单易懂。。。

一、闭包含义

即有权访问另一个函数作用域的变量函数。

二:一个简单的场景

  以上定义大概可以理解,但不知道为什么不把“另一个函数”放在上面。 改成 “包含函数”,因为我觉得“包含函数”可能更通俗易懂,光有定义是不够的。我

还得找一个经典的例子来看看。

1     <script type="text/javascript"> 2  3         //比较函数 4         function createComparison(propertyName) { 5  6             return function (obj1, obj2) { 7                 var item1 = obj1[propertyName]; 8                 var item2 = obj2[propertyName]; 9 10                 if (item1 < item2)11                     return -1;12 13                 if (item1 > item2)14                     return 1;15 16                 if (item1 == item2)17                     return 0;18             }19         }20 21         //比较name22/         var compare = createComparison("name");23 24         var result = compare({ name: "d", age: 20 }, { name: "c", age: 27 });25     </script>

这是一个关于闭包原理的经典例子。经典在哪里?例如,当我使用compare时,我的function可以访问createcomparison函数中的createcomparison

propertyname字段,其实这种理解并不复杂,我们去看看浏览器的scope variables一清二楚。

Javascript之旅——第十站:为什么都说闭包难理解呢?_匿名函数

我们可以清楚地看到,当前执行函数中的本地变量列表清楚地记录在chrome的本地变量表中,并进行了分类,如上述“本地函数变量”(Local)“,

包含函数变量(Closure)",全局变量(Global)“,下面有一个有趣的问题。chrome如何知道当我的代码执行到20行时,当前的local? variables

什么?而且还能给我分类,是不是太精彩了???但是仔细一想,就能豁然开朗。一定有一个保存当前variables的变量,否则,chrome

去哪里读书?对吗????

三:解开谜底

  事实上,每个function都有一个scope属性。当然,这个属性被引擎屏蔽了。你看不见也摸不着。它保存了当前函数 local variables,如

如果应用到上面的demo,全局函数中有一个scope,createcomparison有一个scope,匿名compare有一个scope,这三个scope仍然通过

如果链表链接,画一个简图如下:

Javascript之旅——第十站:为什么都说闭包难理解呢?_chrome_02

从上面的简图可以看出,其实整个函数中有三个scope,每个scope都是用next指针链接的,这样就形成了链表。当我执行下面的代码时

1 var result = compare({ name: "d", age: 20 }, { name: "c", age: 27 });

js引擎将获得当前compare的scope。通过scope属性的next指针,您可以区分哪些变量属于哪个函数,因此您可以看到chrome对variables

分类了。

四:加深对一个案例的理解

  我想在这里阅读。你应该明白封闭包装的原理。事实上,这并不奇怪。这是一个阅读scope属性的问题。我只是被迫变高。让我们来看看下面的代码:

1     <script type="text/javascript"> 2  3         var arr = new Array(); 4  5         function Person() { 6             for (var i = 0; i < 10; i++) { 7  8                 //记住,该属性函数的声明,只有立即执行,才能取scope属性 9                 var item = function () {10                     return i;11                 };12 13                 arr.push(item);14             }15         }16 17         Person();18 19         for (var i = 0; i < arr.length; i++) {20             console.log(arr[i]());21         }22     </script>

在这个例子中,我想做一个function()数组array,最终输出各自的值(1、2、3、4、5...10)但是结果是什么呢?下图可以看到输出

其实是10个10个。。。这违背了我最初的意图。

Javascript之旅——第十站:为什么都说闭包难理解呢?_javascript_03

上面这个陷阱最大的问题是,你认为我在匿名function中写了return i;我认为它属于匿名函数。事实上,这是一个很大的错误,因为即使我去天涯,这个i也是一个很大的错误

海角不是匿名函数,而是包含函数Person,所以原理应该是这样的。例如,当我执行ar[0]()时,匿名函数将通过scope

我去找i,但是匿名函数的scope里没有i,所以我通过next找到了person函数。我确实在person中找到了i,但是这个时候i已经10了,然后scope就结束了。

搜索输出10。解决方案也很简单。只需给每个匿名function一份副本。我想你应该能够用scope推测具体原理,对吗?

Javascript之旅——第十站:为什么都说闭包难理解呢?_chrome_04

上一篇 基于SSM框架开发的小型英语学习网站
下一篇 经典算法题每日演练——第二十五题 块状链表

文章素材均来源于网络,如有侵权,请联系管理员删除。