麻麻,个人for循环里用var为何出错了!

在项目中尽量的使用let和const

你们对这句话是否是很熟悉?咱们无论看文档仍是项目组的人都会提及这几个定义变量的事情,今天小弟给你们说说这几中定义方式的区别node

  • var

    • 说到var那就要从js的出生提及,在最初的草案中js中的全局变量和顶层变量是彻底相等的,也就是全局变量等于window(浏览器)或global(node)
    • 咱们来看段代码
    • var name = 'jack';console.log(window.namne) // jack
    • 我用var定义了一个变量至关于 window.name = 'jack'
    • 其实这种写法也没有什么问题,可是在for里使用你们是否是想起点什么来了?
    • for(var i = 0;i < 5; i++){
            setTimeout(() => {
                console.log(i);
            }, 1000)
        }
        console.log(window.i) // 5
      复制代码
    • 觉得答案是1-5吗?不 其实会输出5次5。
    • var存在状态提高 这是i已是全局变量了,for循环每次循环时看到var就不会从新var而是在自己的基础上++ 因此每次操做的都是全局变量i。打印出来固然是5了
    • 不对,等等。
    • 为何for循环里面不写定时器或者ajax或者event事件单单打印i为何是12345呢?由于在for内部的定时器/ajax/event事件都引用了变量i致使i变量没法被内存机制收回而保存在代码块内部(这里不懂的童鞋能够看看闭包)
    • 因此在单单打印i或者不对i进行操做的话是一切正常的
  • let

    • 说清楚了var所存在的问题就来讲说let。let的定义在网上一搜一大把我就不献丑了,其实for+let在被js引擎解析的时候就会造成一个局部代码块,在局部代码块里let是惟一的,也就是说无论遇到什么状况for在进行循环时都要执行let i = xxx 这就保证了每一次的循环都是一个新值
    • 下面的图片是我查MDN和咨询咱们大佬得出来的结论 你们看看就好啦~
  • var存在的变量提高

    • 由于做用域链的关系在函数内应该先从函数内寻找变量若是函数内没有在寻找上一级直到寻找到或者undefined 这句话必定要记住!!
    • var num = 10
        function fn() {
            console.log(num)
            var num = 20
        }
      复制代码
    • 上述代码应该输出多少?这道题面试官不知道问了几回了 划重点!!
    • 答案是 undefined。var声明的变量是有变量提高的 在函数内部我声明了 var num = 20 //无论我写在函数哪里都会被提高到函数的最顶部 因此这段代码的顺序是:先执行第一句 定义num并赋值10。走到函数内部引擎发现函数内部有var就把这句提到函数顶部至关于:
    • function fn() {
      复制代码
    • var num = 20
            sonsole.log(num)
            // 注意!变量提高只是把声明提到了顶部可是没有赋值因此num是 undefined
        }
      复制代码
    • 那咱们用let定义呢?要记住let是不存在变量提高的因此将代码改成:
    • function fn() {
            console.log(num)
            let num = 20
            // num is not defined
        }
      复制代码
    • 上面说到了做用域链的问题,做用域链实际上是引擎寻找变量的过程,会从内部开始寻找一直寻找到最外部。在上面的代码中fn()内部的num首先会找内部的定义若是有就取内部的没有就找上一级。
    • var num = 10
        function fn() {
            console.log(num)
            var num = 20
        }
      复制代码
    • 这段代码最终的解释是: 因为做用域链我先寻找fn内部的num但因为var存在变量提高到函数顶部 因此我找到了num可是这时的num仍是未定义状态最终返回了 undefined

  • const

    • 就差最后一个const啦。咱们了解es6的童鞋都知道const是定义一个常量用的定义后就不能改变了。
    • 可是看下面的代码
    • const obj = {}
      复制代码
    • obj.name = 'jack'
        obj.sex = 'male'
        为何这样不会报错呢?
      复制代码
    • 咱们从js的数据类型提及,数据类型分为:
      • 基础数据类型:num string ...
      • 复杂数据类型:object array ...
    • 基础数据类型没什么好说的 修改他就直接改变他的值了。要说的是复杂类型 在上面 const obj = {}建立了一个object object是复杂类型他实际上是指向的内存和指针 obj.name = 'jack'只是在内存里有加了一条数据并无直接改变obj的指向因此不会报错。array同理
    • const obj = {}
        obj = []
        你们说这样会不会报错呢?
      复制代码

感悟

-   鲁迅曾经说过 能把本身的知识输出给其余人 才表明你真正懂了

-   我想把本身当时学过的思路和你们分享 
-   上面的demo只是最基本的形式,为了方便说明用的都是全局定义
复制代码