閉包, 定時器

  • 什么是閉包? 有什么作用
    • 閉包的形成
      在高級程序設計3中對于閉包的定義是這樣的
      <blockquote>有權訪問另一個函數(shù)作用域中的變量的函數(shù)。</blockquote>
      在Wikipedia中的定于是這樣的
      <blockquote>引用了自由變量的函數(shù)。</blockquote>
      一開始,我對這樣的抽象概念很模糊,但是當我理解了閉包之后,我又認為這樣的定義是簡介而有力的,如果從理解閉包的定義來說,可以認為JS中的所有函數(shù)都是閉包,因為每個函數(shù)都能訪問到全局作用域的自由變量
var a = 1
function fn() {
    console.log(a)
}
fn()

在這個例子中,fn可以訪問了全局變量a,這個函數(shù)就叫做閉包,當然,這只是從理解的角度來說,實際上這樣的全局作用域下的閉包是沒意義的,因為全局的變量對象不會被銷毀。在函數(shù)內部的閉包可以在chrome的開發(fā)者工具看到


2016-08-19_154334.png

要理解閉包的和閉包的作用,就要從作用域鏈的形成開始,通過下面的例子來說明

var a =2
function fn() {
    var a = 1
    function fn2() {
        console.log(a)
    }
    fn2()
}
fn()

因為js是詞法作用域,當函數(shù)fn聲明的時候,就會預先包含全局作用域鏈,然后放在fn.Scope中,[[Scope]]是一個只有語言內部才能訪問的屬性,當函數(shù)fn被調用的調用的時候,會創(chuàng)建一個執(zhí)行環(huán)境,執(zhí)行環(huán)境里面有兩個東西,一個是變量對象在函數(shù)內部又叫活動對象,一個是作用域鏈,作用域鏈的形成就是復制fn.Scope里面的變量對象,然后推入當前的活動對象。當fn執(zhí)行完的時候,本來fn執(zhí)行環(huán)境的變量對象和作用域鏈都會銷毀,但是現(xiàn)在只有作用域鏈銷毀了,變量對象卻沒有銷毀,因為內部的函數(shù)fn2的作用域鏈在引用這fn的變量對象。因為fn2的作用域鏈里面包含fn的變量對象,所以可以訪問到fn的變量,所以也就形成了閉包。
- 閉包的缺點
1. 在IE9之前因為使用不同的垃圾收集機制會導致循環(huán)引用會造成內存泄漏
2. 閉包會攜帶包含函數(shù)的作用域,所以會比其他函數(shù)占用更多內存,過度使用閉包會造成內存占用過多
- 閉包的用法
其實保存變量現(xiàn)場,封裝私有變量都是對閉包特性的利用,并不是閉包的定義,不要混淆
1. 保存變量現(xiàn)場,主要利用了js函數(shù)傳遞參數(shù)的方式是按值傳遞

!function() {
    var arr = []
    for (var i = 0; i < 5; i++) {
        arr[i] = function () {
            alert(i)
        }
    }
    arr[1]()//5
}()

本來的打算應該數(shù)字的每一項都是一個函數(shù),可以打印出每一項的索引,但是因為所訪問的i是外部函數(shù)的,當循環(huán)完以后,i已經累加到5了,所以無論多少輸出當然是5,我們可以利用js函數(shù)傳遞是按值傳遞的方式來改造這個數(shù)組

!function() {
    var arr = []
    for (var i = 0; i < 5; i++) {
        arr[i] = function (n) {
            return function () {
                alert(n)
            }
        }(i)
    }
    arr[1]()//5
}()

改造后的函數(shù)輸出就是1,主要利用按值傳遞參數(shù)和閉包
2. 封裝私有變量
有時候我們常常需要隱藏一些數(shù)據(jù),而僅僅暴露一些接口供外部使用,起到封裝的效果,這時候就可以利用閉包

var Car = (function () {
    var speed = 0
    return {
        setSpeed: function (s) {
            speed = s
        },
        getSpeed: function () {
            return speed
        }
    }
})()
Car.setSpeed(30)
Car.getSpeed()

這就封裝了一個汽車對象,其中是speed私有的變量,只能通過我們提供的接口setSpeed和getSpeed來訪問到

  • setTimeout 0 有什么作用
    setTimeout表示的是超時調用,setTimeout可以接受多個參數(shù),表示過延遲多長時間再執(zhí)行回調函數(shù)
    • 第一個參數(shù)表示回調函數(shù),可以是一個字符串或者是一個函數(shù)名,推薦使用函數(shù)名,因為字符串會導致一定的損耗和安全問題
    • 第二個參數(shù)表示延遲的時間,單位是ms毫秒,因為js是單線程的解釋器,所以一次只能執(zhí)行一段代碼,為了控制要執(zhí)行的代碼,就有一個任務隊列,這些任務就會按照他們添加到任務隊列的順序執(zhí)行,延遲的時間表示再過多少ms才把當前任務添加到任務隊列,如果隊列前面沒有任務,當前任務就會立即執(zhí)行,如果隊列前面有任務,就要等到前面的任務執(zhí)行完之后再執(zhí)行
    • 第三個和后面的參數(shù)表示參數(shù)回調函數(shù)的參數(shù)
      setTimeout(f,0)表示的就是盡快的執(zhí)行函數(shù)f,他的作用可以調整時間的發(fā)生順序,例如在開發(fā)中,某個事件發(fā)生在子元素,然后冒泡到父元素,即子元素的回調函數(shù)會比父元素的回調函數(shù)先執(zhí)行,通過setTimeout(f,0)我們就可以讓子元素的回調函數(shù)排在隊列后面,從而讓父元素的回調函數(shù)先執(zhí)行
      參考:
      定時器-阮一峰
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 什么是閉包? 有什么作用閉包:函數(shù)對象可以通過作用域鏈相互關聯(lián),函數(shù)體內部的變量可以保存在函數(shù)的作用域內。 上述代...
    coolheadedY閱讀 820評論 0 0
  • 問題 一、什么是閉包? 有什么作用? 閉包閉包就是能夠讀取其他函數(shù)內部變量的函數(shù)。在javascript中,只有函...
    婷樓沐熙閱讀 668評論 0 0
  • 問答 1.什么是閉包? 有什么作用? 閉包 簡而言之 就是讓函數(shù)外部可以訪問函數(shù)內的局部變量,就是將函數(shù)內部和函數(shù)...
    我是小韓閱讀 374評論 1 0
  • 1.什么是閉包? 有什么作用 定義:閉包就是嵌套在函數(shù)里面的內部函數(shù),并且該內部函數(shù)可以訪問外部函數(shù)中聲明的所有局...
    饑人谷區(qū)子銘閱讀 1,080評論 0 2
  • “那時我們有夢,關于文學,關于愛情,關于穿越世界的旅行?!北睄u所說的“那時”大概就是我們這樣一個年紀吧,對于自...
    惜愛汐閱讀 528評論 0 4

友情鏈接更多精彩內容