一个有意思的js块作用域问题
1.问题
首先把问题放出来,昨天看了一个掘友发的一个问题,然后跟我同事一起研究了一下,没找出来是为什么,然后我回来一直在想为什么,然后各种找资料研究,从各个方面找为什么,比如js上下文,作用域,js垃圾回收,堆栈调用情况等等。
2.js断点调试找答案
首先如果不看上面的图,以你现在知道的js知识,你觉得打印出来应该是什么。第二张图其实打印出来的结果在意料之中,原因就是函数声明提升,没问题,但是第一张图为什么呢?这里可以发散一下思维,比如说是不是在块作用域中,变量和函数之间存在某种互相覆盖的问题啊,或者说先在块中声明的会被挂载到全局的window对象下面,后面声明的就挂载不上去了,并且不会覆盖,然后可以把代码稍微改改,验证一下你的思想,很有意思。然后下面我们断点调试看下:
此时我们再看a在块作用域中就已经是方法了,注意此时我function a(){}这段代码还没走完呢,这就说明函数声明在js解析(注意是解析不是执行)的时候被提升到了代码块顶部,进花括号的那一刻起,函数就已经被声明了,我们再往下面一步走
此时a不管在块作用域还是全局作用域中都变成了a函数,那这里是不是可以理解为运行上面一行代码,然后就给全局变量下的a赋值为函数呢,我们再看下一步
当a=50;走完之后,也就出了块作用域,此时我们看到没有了块作用域,因为已经出了块作用域了,然后全局对象window里面a还是函数,并不是50,但是如果你在块作用域a后面加一行的断点看的话,此时块作用域里面的a的值为50,问题就在这里,为什么此时块作用域里面的a的值跟全局window对象下面的值结果不一样呢?
然后我们再往下走一步:
然后进第二个块作用域,发现跟前面进第一个块作用域一样,还没执行第一行,块作用域里面的b已经是函数了,原因也跟第一个一样js解析的时候函数声明提升,然后我们再往下走一步:
这一步走完我们发现块作用域里面的b已经变成50了,但是全局window对象下面的b还是undefined,这我也不知道为什么,那我也就只能说此时b是定义在块作用域中的内部变量了,再往下走一步
但是当我走出块作用域的时候,b竟然在全局对象下变成了50,那就证明我上面说的不对,b不是块作用域中的内部变量,因为此时执行完方法立马就出块作用域了,我们看的不是很清楚,我们在方法下面加一行代码,方便调试看结果:
确实是当我b函数那一步走完,块作用域和全局对象window下面的b都变成了50,那我这里我就认为是函数b在js解析的时候就被提升到了块作用域的最上面,执行到b函数那一步其实在之前就已经执行过了,相当于js执行的时候代码变成下面这样:
{
function b() {};
b = 50;
}
我们再看这个代码不正是上面a那一个块作用域的代码吗,所以在块作用域中js执行的时候上下两个块作用域中是一样的,所以在块作用域中打印a,b得到的结果都是50,然后下一步:
出了块作用域,就只有全局对象window了,然后window对象下面的b还是50,所以最后打印出来也是50。走到这一步就所有的步骤都走完了,那么我们再回头看上面的a为什么块作用域中的值跟window对象下面的a的值不一样,通过走完下面一个代码块我们发现上面代码块跟下面代码块只有函数放的位置不一样,结果就不一样,那我们就看一下这里函数声明提升到底是怎么提升的。
3.块作用域中的函数声明提升
然后我就找到阮一峰博客里面写的关于es6块级作用域的文章:
http://es6.ruanyifeng.com/#docs/let#%E5%9D%97%E7%BA%A7%E4%BD%9C%E7%94%A8%E5%9F%9F
另一篇关于js变量的生命周期的文章:
https://dmitripavlutin.com/variables-lifecycle-and-why-let-is-not-hoisted/
在第一篇文章中,看见里面有真么一段话:
一个有意思的js块作用域问题的更多相关文章
- 一个有意思的js实例,你会吗??[原创]
首先,看看下面一个js例子,你觉得会输出什么呢? function fn(a){ a(); function a(){ console.log(2); } var a = function(){ co ...
- 一个有意思的js小问题
问题:如何实现以下函数? add(2, 5); // 7 add(2)(5); // 7 第一个就不用说了,很简单,关键是看第二个,add(2)(5),可见add(2)应该返回的是一个函数,这个函数再 ...
- 混合开发的大趋势之 一个Android程序员眼中的 React.js 块级作用域 和 let
转载请注明出处:王亟亟的大牛之路 最近都有事干然后,快到月底了这个月给CSDN的博文也就两篇,想想也蛮多天没更了,那就来一篇. 老规矩,先安利:https://github.com/ddwhan012 ...
- 读书笔记-你不知道的JS上-函数作用域与块作用域
函数作用域 Javascript具有基于函数的作用域,每声明一个函数,都会产生一个对应的作用域. //全局作用域包含f1 function f1(a) { var b = 1; //f1作用域包含a, ...
- python 控制语句基础---->代码块:以为冒号作为开始,用缩进来划分作用域,代表一个整体,是一个代码块,一个文件(模块)也称为一个代码块 | 作用域:作用的范围
# ### 代码块:以为冒号作为开始,用缩进来划分作用域,代表一个整体,是一个代码块,一个文件(模块)也称为一个代码块 # ### 作用域:作用的范围 print(11) print(12) prin ...
- js私有作用域(function(){})(); 模仿块级作用域
摘自:http://outofmemory.cn/wr/?u=http%3A%2F%2Fwww.phpvar.com%2Farchives%2F3033.html js没有块级作用域,简单的例子: f ...
- You Don't Know JS: Scope & Closures (第3章: 函数 vs 块作用域)
第二章,作用域由一系列的bubbles组成.每一个都代表了一个container或bucket,装着被声明的identifiers(variables, functions).这些bubbles相互嵌 ...
- ES6中块作用域之于for语句是怎样的?
在ES6中新加了快作用域的概念(C语言就有,作为类c语言的js,当然应该加上),算是很好理解. { let i; } console.log(i);// i is not defined 在代码块当中 ...
- JS的作用域和作用域链
每个函数都有自己的作用域,当执行流进入一个函数时,函数就会被推入栈中,而在函数执行之后,栈将其执行环境弹出,把控制权放回给之前的作用域,全局作用域是最外围的一个作用域,因此,所有全局变量和函数都是作为 ...
随机推荐
- HDU 6315
题意略. 思路:本题的思路总的来说就是暴力 + 剪枝. 我们依然用线段树来维护: 定义结点node{ l , r , minn , contirbute} 分别为某个区间的左右端点,和该区间(b序列) ...
- 第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题
第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题 1.原题呈现 2.试题答案 3.题目解析 因博客园无法打出公式等,所以给你们几个小编推荐的链接去看看,在这里小编深感抱歉! https ...
- 大数乘法(适合k进制)
#include<stdio.h> #include<string.h> #define N 10000 void inv(char str[],int n) { int i, ...
- hdu 5903 Square Distance(dp)
Problem Description A string is called a square string if it can be obtained by concatenating two co ...
- poj 1417 True Liars(并查集+背包dp)
题目链接:http://poj.org/problem?id=1417 题意:就是给出n个问题有p1个好人,p2个坏人,问x,y是否是同类人,坏人只会说谎话,好人只会说实话. 最后问能否得出全部的好人 ...
- Python学习之旅:使用Python实现Linux中的ls命令
一.写在前面 前几天在微信上看到这样一篇文章,链接为:https://mp.weixin.qq.com/s/rl6Sgv3uk_IpoFAx6cWa8w,在这篇文章中,有这样一段话,吸引了我的注意: ...
- github 授权登录教程与如何设计第三方授权登录的用户表
需求:在网站上想评论一篇文章,而评论文章是要用户注册与登录的,那么怎么免去这麻烦的步骤呢?答案是通过第三方授权登录.本文讲解的就是 github 授权登录的教程. 效果体验地址:http://biao ...
- 2019icpc徐州网络赛_I_query
题意 给定一个序列,多次询问区间\([l,r]\)中满足\(min(a[i],a[j])==gcd(a[i],a[j])\)的数对\((i,j)\)数. 分析 其实就是求区间有倍数关系的数对数. 由于 ...
- Day004作业
1,写代码,有如下列列表,按照要求实现每⼀一个功能li = ["alex", "WuSir", "ritian", "barry& ...
- 【LeetCode】BFS 总结
BFS(广度优先搜索) 常用来解决最短路径问题. 第一次便利到目的节点时,所经过的路径是最短路径. 几个要点: 只能用来求解无权图的最短路径问题 队列:用来存储每一层便利得到的节点 标记:对于遍历过的 ...