js作用域链和闭包的理解
来源:互联网 发布:榕基软件股票行情 编辑:程序博客网 时间:2024/06/02 07:31
最近在做一个面试题时,无意中看到了一个闭包的题目,题目很简单,就是一个ul标签下面有多个li,给每个li添加点击事件,要求点击每个li弹出该li是第几个li。作为一个在前端面试中身经百战(lv zhan lv bai)的coder(lowser)来说,我当然知道要使用闭包来解决这个问题,具体代码如下:
var li=document.getElementsByClassName('liClass'); for(var i=0;i<li.length;i++) { (function(num){ li[num].onclick=function(){ alert(num);} })(i) }
或者使用let来声明循环变量,或者在循环类先用一个函数来先返回当前序号,然后在弹出,等等等等等方法都可以解决上述问题。
可是说上述类型的问题 ,遇到过不下于五六次了,虽然每次都能解决此类问题,但是心里一直有个结,就是老是感觉自己对这类问题的原因,有种一知半解的嫌疑,于是今天打算彻底fire掉它。那么问题来了:
什么是js的作用域链?
先展示一段代码:
var scope="global"; function t(){ console.log(scope); //undefined var scope="local" console.log(scope); //local} t();
出现这种情况的原因是,js语法不存在块级作用域,且存在着变量提升的机制。上述代码可以翻译成:
var scope="global"; function t(){ var scope; console.log(scope); //undefined scope="local" ; console.log(scope); //local} t();
很明显了,js中var scope=’local’的声明和赋值,会被拆分为var scope;scope=‘local’;且声明会提升到当前作用域的最前面。
何为作用域?通常来说一段程序代码中使用的变量和函数并不总是可用的,限定其可用性的范围即作用域,作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突。
何为作用域链?当一个函数作用域里面又声明一个函数时,子函数就会继承父函数的作用域,父函数又会继承父父函数的作用域,….一级一级的,直到最顶层的作用域,这就形成了一个作用域链。函数的作用域链是在函数的创建的时候创建。
什么是闭包?
回到最开始的那个题目,写一个错误的实现方法:
var li=document.getElementsByClassName('liClass'); for(var i=0;i<li.length;i++) { li[i].onclick=function(){ alert(i); } }
这是一个错误写法,结果是,不管点击那个li,弹出的都是li.length。通过以上对作用域链的理解,可以得知:
上述代码在页面加载完成后就会执行,for循环执行完成后,i的值变为li.length,当执行点击事件时,后面的匿名函数就是一个闭包,闭包i变量不会被销毁,所以每次都弹出li.length,没 毛病。
回到开头,如果for循环后紧跟使用一个自执行函数,又形成了一个闭包,使用num值保存每次循环的i值,这样就不会有问题了。
问题解决,
- js作用域链和闭包的理解
- 作用域链和闭包理解
- Js函数深入理解-作用域链与闭包
- 简述JS作用域、作用域链和闭包
- javascript中的【变量作用域】和【作用域链】以及【闭包】的理解
- JavaScript关于作用域、作用域链和闭包的理解
- 对于JS语言的深刻理解(变量定义;作用域链;闭包;this)
- js的闭包与作用域/作用域链
- JS的的作用域和闭包
- js作用域和闭包的知识
- 你不知道的JS---作用域和闭包
- JS中的作用域和闭包的小知识点
- {{JS}}函数作用域和闭包
- js闭包和作用域
- js 作用域和闭包1
- js作用域链,js闭包
- js和php中的作用域链的理解
- JS基础知识:变量对象、作用域链和闭包
- eureka-client.properties文件配置
- 你有必要知道的函数式编程
- 序列化
- Docker网络详解-二
- leetcode13
- js作用域链和闭包的理解
- APP切换语言
- SATA,SAS,SSD 读写性能测试结果
- js中innerHTML与innerText的用法与区别
- Docker网络详解-三
- tmux的使用方法和个性化配置
- (41):慎用重载
- 蓝桥杯--入门练习:序列求和
- Vue2.0 之 自带浏览器里无法打开(兼容处理)