麻麻,個人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只是最基本的形式,爲了方便說明用的都是全局定義
複製代碼
相關文章
相關標籤/搜索