JavaScript单线程,异步以及let const var的讨论

在es6之前,我们定义变量都是用的var的方式,但是我确实花了不少的时间理解var的变量定义方式,var定义变量的作用域是整个函数范围,而不是类似于c语言的在一个大括号内,严谨的说也就是没有所谓的“块级作用域”,这被视为是JavaScript的一个缺点,如下代码:

  for(var i=0;i<3;i++)
       {
       setTimeout(function(){
       console.log(i);
       },200)
       }//结果为3,3,3


在了解到闭包,垃圾回收机制之前我对这个结果并不是很理解,但是现在回过头来看就比较清晰了,当然,用到了setTimeout,就必须得先扯开一下聊聊JavaScript的语言特性,首先

它是一门单线程,异步的语言,所谓单线程,就是说JavaScript只能再一个时间内做一件事,举个实际的例子来说,昨天早上我起床叫我室友打LOL,他先起床,后刷牙,耗时7分钟,最后打开电脑等待游戏登陆的3分钟,总耗时10分钟。这样明显会使得做事的效率明显比较低,于是他今天早上学聪明了,起床直接打开游戏登陆,再去刷牙,只用了7分钟,节约了3分钟宝贵的游戏时间,这也就是“异步操作”。那么JavaScript到底是如何做到的呢,实际上,JavaScript,c语言(其他语言我也不晓得~~)的函数的编译原理都是基于“堆栈”这种数据结构的,编译器会把需要执行的函数放入stack中执行则入栈,return则出栈,所以对于某些函数,方法,JavaScript会让它处于等待状态,不会等到它出栈后再让后续函数入栈。

其次:

在JavaScript中有垃圾回收机制,由于对地址的回收,类似于c语言的free函数,至少对于初学者,这是一个优点,但是便利的结果往往是更加纠结,关于这个有趣的机制MDN给出了详细的解释

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management

由此可见,在我们给出的这个例子里,i实际上是一个引用也就是指针,for循环先执行完毕后定时器函数执行,当定时器函数执行时,由于它的内部没有定义i,所以他会沿着他的作用域链寻找i,而此时for循环已经被垃圾回收了,所以i最后的值为for循环结束累加的值;

如何解决这个问题呢,此前我们会利用闭包的方法,将函数嵌套,让i存在引用的对象,也就不会被垃圾回收了,代码如下:

 

for(var i=0;i<3;i++){
      (function(){
           var fn1=(x)=>{
           console.log(x);
       }
       return fn1(i);
      })()
     }//0,1,2


var某些特性解释让代码看起来如此复杂~~~;

那么let将如何解决这个问题呢?

for(let i=0;i<3;i++){
        setTimeout(function(){
            console.log(i);
        })
       }//0,1,2


是不是感觉柳暗花明又一村的,和c语言写循环是一样的,明显的感觉到JavaScript与其他语言相比其独具风格的地方在变少;

综上所述:

let,const的与var的区别在于,var的作用域在整个函数,而前者的作用域仅在父级的大括号;

当然还有其他的小区别:

1:var 会在定义的函数未执行时就被找到,如

     

  alert(i);//undefined
  var i=2;


 而换成let const就会报错

2: const 定义的变量为常量,不可以改变,会报错,同样用let重定义变量会抛出一个语法错误;

3:形如for (let x...)的循环在每次迭代时都为x创建新的绑定。

/*也就是说循环创建的每一个i并不等效,i的值的改变并不是在单纯的在原引用上改变;

参考资料

http://www.infoq.com/cn/articles/es6-in-depth-let-and-const/

https://blog.csdn.net/qq_22855325/article/details/72958345

 

---------------------文章转载至:  用月光取暖----------------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章