当前位置: 首页 > 后端技术 > Node.js

探索js下的let、var和闭包

时间:2023-04-03 23:21:20 Node.js

js是一门非常灵活的语言,写起来真的很容易,但是现在有了typescript,写起来舒服多了。问题是js闭包必须涉及作用域。一般在区分var和let的时候都会给出for循环的例子,但是这里只讲scope,不讲closure,所以其实我还是不懂,觉得很无厘头。在阮一峰的let和const命令那一节,他举了这样一个例子。vara=[];for(vari=0;i<10;i++){a[i]=function(){console.log(i);};}a[6]();//10andvara=[];for(leti=0;i<10;i++){a[i]=function(){console.log(i);};}a[6]();//6然后不知道为什么用了var全局变量后,输出10,但变成块级作用域let后,却正常输出。手上不知道怎么回事,只好debug看看变量长啥样?在两个例子中都添加了一点vara=[];varb;varc;for(vari=0;i<10;i++){b=i;c=我;a[i]=function(){console.log(i);控制台日志(c);};}在这里,循环中有3个变量,其中两个在内部函数中被引用。然后我们循环三遍,看a[0],a[1],发现a[0],a[1]先是一个函数对象,scopes里面有个Closure,就是闭包。这里,闭包中只有i和c,没有b,因为b在内部函数中没有使用,所以不被scopes记录。并且请注意,i和c的值都是当前变量i的值。这也是闭包的一个属性,可以记录内部函数引用外部值。因为i、c、b都是全局变量,循环中不断地覆盖值,闭包不会记录循环过程中的值,只会记录闭包变量。注意:我这里循环了3次,所以闭包变量都是3,如果循环结束,又是另外一个值。你能正确地说出他们的价值观吗?然后我们看一下适配letvara=[];letb;letc;for(leti=0;i<10;i++){b=i;c=我;a[i]=functionoo(){console.log(i);控制台日志(c);};}a[6]();//6同理,还是有i,b,c三个变量,在内部函数中引用了两个。那么我们循环三次之后,再看上图中的a[0],a[1],我们可以看到scopes增加了一个新的东西Block,就是函数记录的blockscope。看这张图,我们可以这样理解:let声明的变量i不是全局变量,每次循环运行都会关闭和重建作用域,但是在内部函数中引用了这个块级作用域变量,所以内部函数会记录这个值。变量c虽然也是let声明,但是为什么没有记录在Block中呢?这是因为变量c是一个let声明,但它在for循环之外。对于这个文件来说,变量c是一个全局变量,所以记录在闭包中了,看了上面的分析,不知道大家对let和const的理解有没有加深。let声明的变量具有块级作用域,const声明的是全局变量,但也要看在什么地方使用。除了闭包时记录的闭包变量和块级作用域变量,我们再看一下输出:vara=[];letb;letc;for(leti=0;i<10;i++){b=我;c=我;变种n=我;让米=我;a[i]=functionoo(){console.log(i);控制台日志(c);控制台日志(n);日志(米);};}a[6]();