JS基础:闭包和作用域链
简介
一个定义在函数内部的函数与包含它的外部函数构成了闭包,内部函数可以访问外部函数的变量,这些变量将一直保存在内存中,直到无法再引用这个内部函数。
例如:
var a = 0;
function outerFun(i) {
var b = i;
function innerFun(j) {
var c = j;
console.log("全局变量:"+a);
console.log("外部变量:"+b);
console.log("内部变量:"+c);
a++;
b++;
c++;
}
return innerFun;
}
var testFun1 = outerFun(10);
testFun1(10);//全局变量:0 外部变量:10 内部变量:10
testFun1(10);//全局变量:1 外部变量:11 内部变量:10 var testFun2 = outerFun(20);
testFun2(20);//全局变量:2 外部变量:20 内部变量:20
testFun2(20);//全局变量:3 外部变量:21 内部变量:20
结论:
c 是 innerFun() 的局部变量,每次执行 innerFun() 都会重新赋值;
b 是 innerFun() 的上一级变量,每次执行 innerFun() 的结果会保存在内存中,是 outerFun() 的局部变量,每次执行 outerFun() 都会重新赋值;
a 是 innerFun() 的上上一级变量,每次执行 innerFun() 的结果会保存在内存中,是 outerFun() 的上一级变量,每次执行 outerFun() 的结果也会保存在内存中;
在JavaScript中,作用域只有全局作用域和函数级作用域两种,在下一级作用域中可以访问和修改上一级作用域的变量,在定义函数时,JS会自动维护一个作用域链,当前的局部作用域位于作用域链顶端,并可以依次向上回溯。闭包的实质就是延长了作用域链。
变量的生存周期
上面提到,js 中只有全局变量和函数级的局部变量两种,全局变量的生存周期当然是永久的,除非我们主动销毁这个全局变量。而对于在函数内用 var 关键字声明的局部变量来说,当退出函数时,这些局部变量即失去了它们的价值,它们都会随着函数调用的结束而被销毁。
例如:
//页面有5个 div,期望点击每个 div 输出它的序号
for(var i=0; i<5; i++) {
$('div').eq(i).on('click',function() {
console.log(i);
})
}
然而,实际上,点击每个 div 输出的都是5,这是因为 i 是全局变量,位于作用域链最顶端,当改变 i 的值的时候,所有引用了它的函数都会受到影响,当循环运行结束后,i 的最终值为5,所以点击每个 div 输出的当然是5了。这时我们可以通过闭包来延长作用域链,为 i 的值保存一个副本,使它们之间不会互相影响。
例如:
for(var i=0; i<5; i++) {
function outerFun() {
var j = i;
function innerFun() {
$('div').eq(j).on('click',function() {
console.log(j);
})
}
innerFun();
}
outerFun();
}
这里的 outerFun() 和 innerFun() 都可以用匿名自执行函数代替,例如:
for(var i=0; i<5; i++) {
(function() {
var j = i;
(function() {
$('div').eq(j).on('click',function() {
console.log(j);
})
})();
})();
}
JS基础:闭包和作用域链的更多相关文章
- [ JS 进阶 ] 闭包,作用域链,垃圾回收,内存泄露
原网址:https://segmentfault.com/a/1190000002778015 1. 什么是闭包? 来看一些关于闭包的定义: 闭包是指有权访问另一个函数作用域中变量的函数 --< ...
- JS闭包、作用域链、垃圾回收、内存泄露相关知识小结
补充: 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变 ...
- Javascript中闭包的作用域链
作用域定义了在当前上下文中能够被访问到的成员,在Javascript中分为全局作用域和函数作用域,通过函数嵌套可以实现嵌套作用域. 闭包一般发生在嵌套作用域中.闭包是JavaScript最强大的特性之 ...
- JS基础篇之作用域、执行上下文、this、闭包
前言:JS 的作用域.执行上下文.this.闭包是老生常谈的话题,也是新手比较懵懂的知识点.当然即便你作为老手,也未必真的能理解透彻这些概念. 一.作用域和执行上下文 作用域: js中的作用域是词法作 ...
- js学习笔记之作用域链和闭包
在学习闭包之前我们很有必要先了解什么是作用域链 一.作用域链 作用域链是保证对执行环境有权访问的所有变量和函数的有序访问. 这句话其实还是蛮抽象的,但是通过下面一个例子,我们就能清楚的了解到作用域链了 ...
- 对js中闭包,作用域,原型的理解
前几天,和朋友聊天,聊到一些js的基础的时候,有一种‘好像知道,好像又不不知道怎么讲的感觉’...于是捡起书,自己理一理,欢迎拍砖. 闭包 理解闭包首先要理解,js垃圾回收机制,也就是当一个函数被执行 ...
- javascript闭包和作用域链
最近在学习前端知识,看到javascript闭包这里总是云里雾里.于是翻阅了好多资料记录下来本人对闭包的理解. 首先,什么是闭包?看了各位大牛的定义和描述各式各样,我个人认为最容易一种说法: 外部函数 ...
- Javascript——闭包、作用域链
1.闭包:是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式:在一个函数内部创建另一个函数. function f(name){ return function(object){ var ...
- JS -- The Scope Chain 作用域链
The Scope Chain JavaScript is a lexically scoped language: the scope of a variable can be thought of ...
随机推荐
- 03一些View总结
第三天 一 TextView 父类 : View >概念:文本控件 :文本内容的显示 默认配置不可编辑 子类EditText可以编辑 >属性: ...
- UNIX环境高级编程——线程属性
pthread_attr_t 的缺省属性值 属性 值 结果 scope PTHREAD_SCOPE_PROCESS 新线程与进程中的其他线程发生竞争. detachstate PTHREAD_CREA ...
- Web Service进阶(五)SOAPBinding方式讲解
Web Service进阶(五)SOAPBinding方式讲解 Java API for XML Web Services (JAX-WS) 2.0 (JSR 224) Standard Implem ...
- Hibernate查询之SQL查询,查询结果用new新对象的方式接受,hql查询,通过SQL查询的结果返回到一个实体中,查询不同表中内容,并将查到的不同表中的内容放到List中
package com.ucap.netcheck.dao.impl; import java.util.ArrayList;import java.util.List; import org. ...
- [C++学习历程]Visual Studio 2010 的HelloWorld
大学时期曾学过C++的知识,那时候也没有使用VS这样高档的IDE工具,就是C++6.0那样来的.对于重新拾起C++来说,换了个IDE,那么就先从使用IDE学起吧~ 作者:苏生米沿 本文链接:http: ...
- Android代码(Handler的运用),HttpURLConnection的应用,将url图片地址转换成图片。
1 布局文件, <LinearLayout 秒, 抛异常 conn.connect(); // 开始链接 int responseCode = conn.getResponseC ...
- 敏捷测试(1)--TDD概念
题记 本系列笔记将从测试人员的角度,总结在百度两年来的测试经验,记录一个完整的基于敏捷流程的验收测试全过程,分享在测试过程中的一些知识和经验,以及自己的一些理念.总结自己,也希望对大家有益. 概念 验 ...
- LCS问题(最长公共子序列)-动态规划实现
问题描述: 问题] 求两字符序列的最长公共字符子序列 注意: 并不要求子串(字符串一)的字符必须连续出现在字符串二中. 思路分析: 最优子结构和重叠子问题的性质都具有,所以要采取动态规划的算法 最长公 ...
- [WinForm]dataGridView背景色交替
方法一: //设置表格背景色 dgvSaleOrder.RowsDefaultCellStyle.BackColor = Color.Ivory; //设置交替行的背景色 dgvSaleOrder.A ...
- my project 中git使用过程(基本操作流程)
1.g it clone git@name:server/BM/APPS.git 则BM_APPS.git项目被下载到当前目录下了,这时git@name:server/BM/APPS.git就是自己 ...