博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript 闭包
阅读量:6981 次
发布时间:2019-06-27

本文共 1981 字,大约阅读时间需要 6 分钟。

闭包的概念及应用。

闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数.

这个函数会返回一个函数数组。表面上看,似乎每个函数都应该返自己的索引值,即位置0的函数返回 0,位置 1 的函数返回1,以此类推。

但实际上,每个函数都返回10。因为每个函数的作用域链中都保存着 createFunctions() 函数的活动对象 , 所以它们引用的都是同一个变量i。 当createFunctions()函数返回后,变量i的值是10,此时每个函数都引用着保存变量 i的同一个变量对象,所以在每个函数内部 i 的值都是 10。

function createFunctions() {    var result = new Array();    for (var i = 0; i < 10; i++) {        // 这里只是把匿名函数push进数组 并没有真正执行        // 因为这里只是一个声明 并没有调用        result[i] = function () {            return i;        };    }    return result;}var funcs = createFunctions();for (var i = 0; i < funcs.length; i++) {    // 调用这个函数的时候才执行 在那个作用域中i的值为10    console.info(funcs[i]());}复制代码

修改通过创建另一个匿名函数强制让闭包的行为符合预期

for (var i = 0; i < 10; i++) {    result[i] = function (num) {        return function () {            return num;        };    }(i);}复制代码

创建块级作用域

用作块级作用域(通常称为私有作用域)的匿名函数的语法如下所示。

(function(){    //这里是块级作用域})();复制代码

以上代码定义并立即调用了一个匿名函数。 将函数声明包含在一对圆括号中,表示它实际上是一个函数表达式。而紧随其后的另一对圆括号会立即调用这个函数。 如果有读者感觉这种语法不太好理解,可以再看看下面这个例子。

var count = 5;outputNumbers(count);复制代码

这里初始化了变量 count,将其值设置为5。当然,这里的变量是没有必要的,因为可以把值直接传给函数。为了让代码更简洁,我们在调用函数时用 5 来代替变量 count,如下所示。

outputNumbers(5);复制代码

这样做之所以可行,是因为变量只不过是值的另一种表现形式,因此用实际的值替换变量没有问题。 再看下面的例子。

var someFunction = function(){     //这里是块级作用域};someFunction();复制代码

这个例子先定义了一个函数,然后立即调用了它。定义函数的方式是创建一个匿名函数,并把匿名函 数 赋 值 给 变 量 someFunction 。 而 调 用 函 数 的 方 式 是 在 函 数 名 称 后 面 添 加 一 对 圆 括 号 , 即someFunction()。通过前面的例子我们知道,可以使用实际的值来取代变量 count,那在这里是不是也可以用函数的值直接取代函数名呢? 然而,下面的代码却会导致错误。

function(){//这里是块级作用域}(); //出错!复制代码

这段代码会导致语法错误,是因为 JavaScript 将 function 关键字当作一个函数声明的开始,而函数声明后面不能跟圆括号。然而,函数表达式的后面可以跟圆括号。要将函数声明转换成函数表达式, 只要像下面这样给它加上一对圆括号即可。

(function(){//这里是块级作用域})();复制代码

使用块级作用域后的改进

for (var i = 0; i < 10; i++) {    // 构造块级作用域 将i传给index    // 这里会立即执行 (function (index)) 因为这就是一个调用函数的表达式    // 从而创建了块级作用域保存了当前的i    // 但是不会立即执行 result[i] = function()    // 以为这里只是声明 并没有调用    (function (index) {        result[i] = function () {            return index;        };    })(i);}复制代码

转载地址:http://wqnpl.baihongyu.com/

你可能感兴趣的文章
/lib /usr/lib /usr/local/lib区别
查看>>
HDU - 5008 Boring String Problem (后缀数组+二分法+RMQ)
查看>>
Swift - 实现点击UITableView单元格时自动展开单元格
查看>>
Cocos2d-x3.0 Button
查看>>
图解.NET Stack和Heap的本质区别
查看>>
Matlab中struct的用法
查看>>
Mysql LIMIT如何正确对其进行优化
查看>>
Spring10种常见异常解决方法
查看>>
近期小结
查看>>
glog 使用
查看>>
C#中的线程(三) 使用多线程
查看>>
深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP
查看>>
onSaveInstanceState和onRestoreInstanceState触发的时机
查看>>
设计模式学习02—工厂模式
查看>>
html5--6-10 CSS选择器7--伪类选择器
查看>>
激光数据匹配(MATLAB Robotics System Toolbox)
查看>>
file_put_contents执行返回false,file_put_contents false(linux服务器httpd)
查看>>
Dependency Walker (depends.exe) Home Page
查看>>
Android---- 如何把calendar.getTimeInMillis()获得的毫秒时间
查看>>
Java学习JVM搞搞Jconsole呗
查看>>