js闭包
看完闭包的概念后发现其实闭包和面向对象编程的对象的私有变量的访问很像,就像是你在java中定义了一个对象,然后用private声明了一个私有变量,那么这个私有变量只有该对象内的函数可以访问,在对象外的其他函数是不可以访问的,那么外面的函数要访问应该怎么办呢?面向对象编程中会写对应的get方法来获取私有变量,要访问该私有变量时就调用该对象的get方法,闭包和这个很类似,javascript中局部变量是不可以被全局函数调用的,所以要调用要用一个函数来获取对应的局部变量。所以,可以把父函数当作对象(object)使用,把闭包当作它的公用方法,把内部变量当作它的私有属性。简单来说就是闭包是指有权访问另一函数作用域中的变量的函数。清晰的讲:闭包就是一个函数,这个函数能够访问其他函数的作用域中的变量。
闭包是依据词法作用域产生的必然结果。通过变相引用函数的活动对象导致其不能被回收,然而形成了依然可以用引用访问其作用域链的结果。
下面我们来看一个例子:
function f1(){
n = 999;
function f2(){
console.log(n); //999
}
}
在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量对f1就是不可见的。这就是javascript语言特有的‘链式作用域’结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们就可以在f1外部读取它的内部变量了。
function f1(){
n = 999;
function f2(){
console.log(n);
}
return f2;
}
var result = f1(); //返回的是f2函数
result(); //999
再来一个例子:
for (var i = 1; i <= 5; i++) { setTimeout( function timer() { console.log(i); }, 1000 ); }
这段代码不仔细看以为会依次输出1 2 3 4 5,但是,一实践发现它其实输出了5 5 5 5 5。这是因为js是单线程的,所以在执行for循环的时候定时器setTimeout被安排到任务队列中排队等待执行,而在等待过程中for循环就已经在执行,等到setTimeout可以执行的时候,for循环已经结束,i的值也已经变成5,所以打印出来五个5,那么我们为了实现预期结果应该怎么改这段代码呢?
for (var i = 1; i <= 5; i++) { (function(i){ setTimeout( function () { console.log(i); }, 1000 ); })(i); }
引入闭包来保存变量i,将setTimeout放入立即执行函数中,将for循环中的循环值i作为参数传递,1000毫秒后同时打印出1 2 3 4 5。
同时我们返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
function count() { var arr = []; for (var i=1; i<=3; i++) { arr.push(function () { return i * i; }); } return arr; } var results = count(); var f1 = results[0]; var f2 = results[1]; var f3 = results[2];
在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都添加到一个Array
中返回了。
你可能认为调用f1()
,f2()
和f3()
结果应该是1
,4
,9
,但实际结果是调用f1()
,f2()
和f3()
结果都是16。
如果一定要引用循环变量,方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变。
function count() { var arr = []; for (var i=1; i<=3; i++) { arr.push((function (n) { return function () { return n * n; } })(i)); } return arr; } var results = count(); var f1 = results[0]; var f2 = results[1]; var f3 = results[2]; f1(); // 1 f2(); // 4 f3(); // 9
https://www.cnblogs.com/onepixel/p/5062456.html
https://blog.csdn.net/dovlie/article/details/76339244
原文地址:https://www.cnblogs.com/tutuj/p/11042195.html
- 万恶的剪贴板==》为存储而生
- AdaBoost算法(R语言)
- CTF---Web入门第六题 因缺思汀的绕过
- 小案例(六):预测小偷行为(python)
- 小案例(五):销量预测(python)
- SQL:插入指定标识列的数据时候的小错误
- 逻辑回归与梯度下降详解
- 决策树(R语言)
- ExecuteReader在执行有输出参数的存储过程时拿不到输出参数
- CTF---Web入门第十三题 拐弯抹角
- 小案例(四):销售额下滑(python)
- 【最新TensorFlow1.4.0教程01】TF1.4.0介绍与动态图机制 Eager Execution使用
- 把插入的数据自动备份到另一个表中 ~ 语境:本地和服务器自动同步
- 数据分析小案例(三):调查问卷(python)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- python第四十六课——函数重写
- Linux系统Memcached服务介绍
- python第四十七课——类属性和函数属性
- python第四十八课——类函数和对象函数
- python第四十九课——对象序列化与反序列化
- python第五十课——多态性
- python第五十一课——__slots
- Linux系统安全配置iptables服务介绍
- ThreadLocal企业中真实应用
- python第五十二课--自定义异常类
- python第五十三课——time模块
- 从亲身经历谈谈如何用Git分支解决项目生产实践中的痛点
- mysql数据库基础命令(一)
- Linux系统Logrotate服务介绍
- python五十四课——datetime模块