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 ...
随机推荐
- Android的ImageSwitcher和TextSw-android学习之旅(三十四)
ImageSwitcher简介 ImageSwitcher继承了ViewSwitcher,所以在切换时候会有动画,可以把它理解成一个动画版本的ImageView. 他的showNext(),和show ...
- java根据概率生成数字
/** * JAVA 返回随机数,并根据概率.比率 * @author zhanglei * */ public class MathRandom { /** * 0出现的概率为%50 */ publ ...
- Mat, IplImage, CvMat, Cvarr关系及元素获取
自己目前正打算整理opencv数据结构之间关系,寻寻觅觅之间,发现这篇博文很全面,总结得很好,故转之.红色部分不对,自己已修改! 原文地址:http://blog.csdn.net/abcjennif ...
- iOS中 Swift初级入门学习(二)
// Copyright (c) 2015年 韩俊强. All rights reserved. // import Foundation /* // 控制语句 // for - in // 遍历字符 ...
- UNIX环境高级编程——信号说明列表
$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGK ...
- Cocos2D:塔防游戏制作之旅(七)
用这3个变量,你可以创建多种不同类型的炮塔,它们可以有着不同的攻击属性,比如长距离重型攻击力,但是慢速攻击的炮塔,或者是渴望快速攻击但是攻击范围近的炮塔. 最后,代码包括了一个draw方法,它在炮塔周 ...
- python发送post请求
urllib2.urlopen() urlib2是使用各种协议完成打开url的一个扩展包.最简单的使用方式是调用urlopen方法,比如 def urlopen(url, data=None, tim ...
- [Django] 单元测试小记
从前很少写单元测试了,特别是web应用.最近不知不觉喜欢起来这个事情了,发现单元测试对于软件的模块,正交性有很大促进作用,因为函数,模块写的不合理,单元测试写起来就麻烦的多呀.公司的项目一直都是用Dj ...
- C语言实现的猜数字小游戏(主要是对于自定义函数的运用)
#include <stdio.h> #include <stdlib.h> #include<time.h>//加上此头文件的作用是什么?另外不加的话有什么影响? ...
- 02_创建Git仓库,克隆仓库,git add,git commit,git push,git pull,同行冲突,不同行冲突的结局方案,git mergetool的使用
1 创建Git资源库,残酷目录信息 创建git资源库的命令: git init –bare 仓库名称 (其中-bare表示的意思是空的库的意思) 进入E:\software\repository\gi ...