欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Javascript作用域與閉包詳情

 更新時間:2021年10月20日 17:00:19   作者:南玖  
相信絕大多數同學都聽過閉包這個概念,但閉包具體是什么估計很少有人能夠說的很詳細。說實話閉包在我們平時開發(fā)中應該是很常見的,并且在前端面試中閉包也是常見的重要考點,在學習閉包之前我們先來看看作用域與作用域鏈,因為這是閉包的關鍵。

1、作用域

簡單來說,作用域是指程序中定義變量的區(qū)域,它決定了當前執(zhí)行代碼對變量的訪問權限

在ES5中,一般只有兩種作用域類型:

  • 全局作用域:全局作用域作為程序的最外層作用域,一直存在
  • 函數作用域:函數作用域只有在函數被定義時才會被創(chuàng)建,包含在父級函數作用域或全局作用域中

說完概念,我們來看下面這段代碼:

var a = 100
function test(){
    var b = a * 2
    var a = 200
    var c = a/2
    console.log(b)
    console.log(c)
}
test()      // 這里會打印出什么?

解析:

  • 首先這段代碼形成了全局作用域與函數作用域
  • 全局作用域有一個變量a賦值為100
  • 在test函數作用域中定義了局部變量b,a,c
  • 這里又存在變量提升,在函數作用域內先進行變量提升var b; var a; var c;
  • 再對b進行賦值,這時候a還沒有被賦值,所以a的值為undefined,再將a*2,所以b為NaN
  • 再給a賦值為200,c賦值為a/2等于100

所以最終會打印出 NaN,100

在ES6中,新增了一種塊級作用域

簡單來說,花括號{...}內的區(qū)域就是塊級作用域,但Javascript并不是原生支持塊級作用域的,需要借助ES6提出的letconst來創(chuàng)建塊級作用域

// ES5
if(true) {
  var name = '南玖'
}
console.log(name)  // 南玖

// ES6
if(true) {
  let age = 18
}
console.log(age)  // 這里會報錯

2、作用域鏈

當可執(zhí)行代碼內部訪問變量時,會先查找當前作用域下有無該變量,有則立即返回,沒有的話則會去父級作用域中查找...一直找到全局作用域。我們把這種作用域的嵌套機制稱為作用域鏈

3、詞法作用域

詞法作用域是作用域的一種工作模型,詞法作用域是JavaScript中使用的一種作用域類型,詞法作用域也可以被叫做靜態(tài)作用域。

所謂的詞法作用域就是在你寫代碼時將變量和作用域寫在哪里來決定的,也就是詞法作用域是靜態(tài)的作用域,在你寫代碼時就決定了。函數作用域取決于它申明的位置,與實際調用的位置無關

MDN對閉包的定義:

一個函數和對其周圍(詞法環(huán)境)的引用捆綁在一起(或者說函數被引用包圍),這樣一個組合就是閉包(closure

也就是說,閉包讓你可以在一個內層函數中訪問到其外層函數的作用域。在JavaScript中,每當創(chuàng)建一個函數,閉包就會在函數創(chuàng)建的同時被創(chuàng)建出來。

我們可以得出:

閉包 = 函數 + 外層作用域

我們先來看段代碼:

var name = '前端南玖'

function say() {
  console.log(name)
}
say()

解析:say函數可以訪問到外層作用域的變量a,那么這樣不就是形成了一個閉包嗎?

在《Javascript權威指南》書中有這樣一句話:嚴格來講,所以JavaScript函數都是閉包

但這只是理論上的閉包,與我們平時使用的不太一樣。上面這個例子只是一個簡單的閉包。

ECMAScript對閉包的定義:

  • 從理論上來講:所有函數都是閉包。因為它們在創(chuàng)建的時候就已經上層上下文的數據保存起來了。
  • 從實踐上來講:閉包應該滿足兩個條件:1.在代碼中引用了外層作用域的變量;2.即使創(chuàng)建它的上下文已經銷毀,它仍然存在;

我們再看一段《JavaScript權威指南》上的代碼:

let scope = 'global scope'
function checkscope(){
  let scope = 'local scope'
  function f(){
    return scope
  }
  return f
}

let s = checkscope()   
s()   // 這里返回什么?

很多同學可能覺得是global scope,但真的是這樣嗎,我們一起來看下它的執(zhí)行過程:

  • 首先執(zhí)行全局代碼,創(chuàng)建全局執(zhí)行上下文,定義全局變量scope并賦值
  • 申明checkscope函數,并創(chuàng)建該函數的執(zhí)行上下文,創(chuàng)建局部變量scope并賦值
  • 申明f函數,創(chuàng)建該函數的執(zhí)行上下文
  • 執(zhí)行checkscope函數,該函數又返回了一個f函數賦值給了變量s
  • 執(zhí)行s函數,相當于執(zhí)行了f函數。這里返回的scopelocal scope。至于為什么是local scope,我們上面講到了詞法

作用的基本規(guī)則:JavaScript函數是使用定義它們的作用域來執(zhí)行的。在定義f函數的作用域中,變量scope的值為local scope

5、閉包的應用

閉包的應用,絕大多是都是在維護內部變量的場景下使用

6、閉包的缺陷

  • 由于閉包的存在可能會造成變量常駐內存,使用不當會造成內存泄漏
  • 內存泄漏可能會導致應用程序卡頓或崩潰

7、高頻閉包面試題

var arr = []
for(var i=0;i<3;i++){
    arr[i] = function(){
        console.log(i)
    } 
}
arr[0]()  // 3
arr[1]()  // 3
arr[2]()  // 3
// 這里在執(zhí)行的時候i已經變成了3

// 使用閉包解決
var arr = []
for(var i=0;i<3;i++){
    arr[i] = (function(i){
        return function(){
            console.log(i)
        } 
    })(i)
    
}
arr[0]()  // 0
arr[1]()  // 1
arr[2]()  // 2

到此這篇關于Javascript作用域與閉包詳情的文章就介紹到這了,更多相關Javascript作用域與閉包內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JavaScript中Reduce10個常用場景技巧

    JavaScript中Reduce10個常用場景技巧

    這篇文章主要為大家介紹了JavaScript中Reduce10個常用場景和技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • 特殊字符、常規(guī)符號及其代碼對照表

    特殊字符、常規(guī)符號及其代碼對照表

    特殊字符、常規(guī)符號及其代碼對照表...
    2006-06-06
  • JavaScript?DOM操作之獲取元素方式全解析

    JavaScript?DOM操作之獲取元素方式全解析

    這篇文章主要為大家介紹了JavaScript全解析之DOM操作及獲取元素的方法全面解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • 實現一個簡單得數據響應系統

    實現一個簡單得數據響應系統

    這篇文章主要介紹了實現一個簡單得數據響應系統,文章介紹的數據響應系統會用到Dep,其實,這就是一個依賴收集的容器, depend 收集依賴, notify 觸發(fā)依賴,下面來看看詳細的內容結介紹,需要的朋友可以參考一下
    2021-11-11
  • 微信小程序 (八)View組件詳細介紹

    微信小程序 (八)View組件詳細介紹

    這篇文章主要介紹了微信小程序 View組件詳細介紹的相關資料,需要的朋友可以參考下
    2016-09-09
  • JavaScript基本語法講解

    JavaScript基本語法講解

    這篇文章主要介紹了JavaScript的基本語法,包括注釋和書寫格式等基本知識,需要的朋友可以參考下
    2015-06-06
  • 無感知刷新Token示例簡析

    無感知刷新Token示例簡析

    這篇文章主要為大家介紹了無感知刷新Token及認證原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • 微信小程序 繪圖之餅圖實現

    微信小程序 繪圖之餅圖實現

    這篇文章主要介紹了微信小程序 繪圖之餅圖實現的相關資料,需要的朋友可以參考下
    2016-10-10
  • JavaScript函數柯里化

    JavaScript函數柯里化

    這篇文章主要介紹了JavaScript函數柯里化,柯里化即Currying是把接受多個參數的函數變換成接受一個單一參數函數,并且返回接受余下的參數且返回結果的新函數的技術,下面文章詳細內容,需要的朋友可以參考一下
    2021-11-11
  • JS創(chuàng)建對象的四種方式

    JS創(chuàng)建對象的四種方式

    這篇文章主要給大家分享JS創(chuàng)建對象的四種方式,分別是字面量的方式去創(chuàng)建對象、使用new字符創(chuàng)建對象、自定義構造函數、工廠模式創(chuàng)建對象,更多詳細內容,請參考下面文章的具體內容
    2021-11-11

最新評論