亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

深入學(xué)習(xí)js之——詞法作用域和動態(tài)作用域

shiweifu / 2268人閱讀

摘要:在中的應(yīng)用采用詞法作用域,也就是靜態(tài)作用域。那什么又是詞法作用域或者靜態(tài)作用域呢請繼續(xù)往下看靜態(tài)作用域與動態(tài)作用域因為采用的是詞法作用域函數(shù)的作用域在函數(shù)定義的時候就決定了。

開篇

當(dāng)我們在開始學(xué)習(xí)任何一門語言的時候,都會接觸到變量的概念,變量的出現(xiàn)其實是為了解決一個問題,為的是存儲某些值,進(jìn)而,存儲某些值的目的是為了在之后對這個值進(jìn)行訪問或者修改,正是這種存儲和訪問變量的能力將狀態(tài)給了程序。我們的程序中到處都充斥著對于狀態(tài)的判斷,根據(jù)不同的狀態(tài)執(zhí)行不同的邏輯。

我們試想一下,如果沒有狀態(tài)這個概念,程序雖然也能夠執(zhí)行一些簡單的任務(wù),但是它會受到很多的限制,所能完成的功能是有限制的,舉個例子,沒有狀態(tài)你是如何執(zhí)行循環(huán)語句?沒有狀態(tài)如何更加優(yōu)雅地使用邏輯結(jié)構(gòu)

仔細(xì)想想,好像是寸步難行,當(dāng)然引入變量后幫我們解決了這個問題。

但是,引入變量和狀態(tài)的概念之后會引起幾個問題:這些變量住在哪里?換句話說,它們存儲在哪里?最重要的是,程序需要它們的時候如何找到它們?

今天我們就一起學(xué)習(xí)一下這套存儲和查找變量的規(guī)則,這套規(guī)則我們稱之為:作用域。

作用域

我們來拆解一下這個詞語,所謂的“”我們可以理解為:范圍、區(qū)域,加上“作用”兩個字所要表述的問題就是作用的范圍、區(qū)域,比如國家的行政區(qū)域劃分是為了便于管理,類比到程序源代碼中作用域的出現(xiàn)也是為了便于對于變量做管理。

好,這里我們簡單做一下總結(jié):

定義:作用域是指程序源代碼中定義變量的區(qū)域。

作用:作用域規(guī)定了如何查找變量,也就是確定當(dāng)前執(zhí)行代碼對變量的訪問權(quán)限。

在javaScript中的應(yīng)用 :JavaScript采用詞法作用域(lexical scoping),也就是靜態(tài)作用域

那什么又是 詞法作用域或者靜態(tài)作用域呢?

請繼續(xù)往下看

靜態(tài)作用域與動態(tài)作用域

因為javaScript采用的是詞法作用域,函數(shù)的作用域在函數(shù)定義的時候就決定了。
而詞法作用域相對的是動態(tài)作用域,函數(shù)的作用域是在函數(shù)調(diào)用的時候才決定的。
讓我們看一個例子來理解詞法作用域和動態(tài)作用域之間的區(qū)別:

var value = 1;

function foo() {
  console.log(value);
}

function bar() {
  var value = 2;
  foo();
}

bar();
// 結(jié)果是 ???

上面的代碼中:

1.我們首先定義了一個value,并賦值為1;

2.聲明一個函數(shù)foo,函數(shù)的功能是打印 value 這個變量的值;

3.聲明一個函數(shù)bar,函數(shù)內(nèi)部重新創(chuàng)建了一個變量 value 這個變量賦值為2;
在函數(shù)內(nèi)部執(zhí)行了 foo() 這個函數(shù);

4.執(zhí)行 bar() 這個函數(shù)

假設(shè)javaScript采用靜態(tài)作用域,讓我們分析下執(zhí)行過程:

執(zhí)行foo函數(shù),首先從 foo 函數(shù)內(nèi)部查找是否有變量 value ,如果沒有
就根據(jù)書寫的位置,查找上面一層的代碼,我們發(fā)現(xiàn)value等于1,所以結(jié)果會打印 1。

假設(shè)javaScript采用動態(tài)作用域,讓我們分析下執(zhí)行過程:

執(zhí)行foo函數(shù),依然是從 foo 函數(shù)內(nèi)部查找是否有局部變量 value。如果沒有,
就從調(diào)用函數(shù)的作用域,也就是 bar 函數(shù)內(nèi)部查找 value 變量,所以結(jié)果會打印 2。

上面在區(qū)分靜態(tài)作用于和動態(tài)作用域的時候,我們已經(jīng)說了如果是靜態(tài)作用域,那么函數(shù)在書寫定義的時候已經(jīng)確定了,而動態(tài)作用域是函數(shù)執(zhí)行過程中才確定的。

JavaScript采用的是靜態(tài)作用域,所以這個例子的結(jié)果是 1。
我們在控制臺中輸入執(zhí)行上面的函數(shù),檢驗一下執(zhí)行結(jié)果果然是 1。

動態(tài)作用域

那什么語言是采用的動態(tài)的作用域呢? 其實bash 就是動態(tài)作用域,
我們可以新建一個 scope.bash 文件將下列代碼放進(jìn)去,執(zhí)行一下這個腳本文件:

#!/bin/bash

value=1
function foo () {
    echo $value;
}
function bar () {
  local value=2;
  foo;
}
bar

上面代碼運行的結(jié)果輸出2很好解釋,雖然在代碼最上層定義了 value并賦值為1,但是在調(diào)用foo函數(shù)的時候,在查找 foo 內(nèi)部沒有 value 變量后,會在foo 函數(shù)執(zhí)行的環(huán)境中繼續(xù)查找,也就是在bar 函數(shù)中查找,很幸運我們找到了。

思考

最后,讓我們看一個《JavaScript權(quán)威指南》中的例子:

// 例1:
var scope = "global scope";
function checkscope(){
  var scope = "local scope";
  function f(){
    return scope;
  }
  return f();
}
checkscope();

// 例2:
var scope = "global scope";
function checkscope(){
  var scope = "local scope";
  function f(){
    return scope;
  }
  return f;
}
checkscope()();

讓我們來分析一下上面例1的代碼:

1、定義一個變量 scope 并賦值 global scope;

2、聲明一個函數(shù) checkscope ,在這個函數(shù)中 定義一個變量 scope 并賦值 local scope;

3、在checkscope 函數(shù)中 又定義一個函數(shù) f ,這個函數(shù) 只做了一件事:返回scope 這個變量;

4、最后返回并執(zhí)行 f 這個函數(shù);

5、調(diào)用checkscope

按照我們上面解釋的javaScript中靜態(tài)作用域理解,在執(zhí)行 checkscope 這個函數(shù)的時候在函數(shù)內(nèi)部執(zhí)行的是f 這個函數(shù),首先在 f 這個函數(shù)內(nèi)部查找 scope 這個變量發(fā)現(xiàn)沒有,繼續(xù)在定義函數(shù)f的上面一層查找,發(fā)現(xiàn)在checkscope 這個函數(shù)作用域內(nèi) 找到了scope的值 直接返回,至于 checkscope外面定義的scope沒有理睬。

讓我們來分析一下上面例2的代碼:

1、定義一個變量 scope 并賦值 global scope;

2、聲明一個函數(shù) checkscope 在這個函數(shù)中 定義一個變量 scope 并賦值 local scope;

3、在checkscope 函數(shù)中 又定義一個函數(shù) f 這個函數(shù) 只做了一件事:返回scope 這個變量;

4、最后單純的返回 f 這個函數(shù);

5、調(diào)用checkscope

按照我們上面解釋的javaScript中靜態(tài)作用域理解,在執(zhí)行 checkscope 這個函數(shù)的時候在函數(shù)內(nèi)返回了函數(shù)f實際是在最外面調(diào)用的f但是由于javaScript是采用的詞法作用域,因此函數(shù)的作用域基于函數(shù)創(chuàng)建的位置。

而引用《JavaScript權(quán)威指南》的回答就是:

JavaScript 函數(shù)的執(zhí)行用到了作用域鏈,這個作用域鏈?zhǔn)窃诤瘮?shù)定義的時候創(chuàng)建的。嵌套的函數(shù) f() 定義在這個作用域鏈里,其中的變量 scope 一定是局部變量,不管何時何地執(zhí)行函數(shù) f(),這種綁定在執(zhí)行 f() 時依然有效。

但是在這里真正想讓大家思考的是:

雖然兩段代碼執(zhí)行的結(jié)果一樣,但是兩段代碼究竟有哪些不同呢?

敬請期待下面一篇關(guān)于javaScript 中的執(zhí)行上下文棧的相關(guān)內(nèi)容。

參考:

1、《你不知道的Javascript上卷》

2、JavaScript深入之詞法作用域和動態(tài)作用域

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/101512.html

Failed to recv the data from server completely (SIZE:0/8, REASON:closed)