js之做用域鏈

js採用的是詞法做用域鏈,在代碼書寫階段,做用域鏈就被定義了,因此 對於新手來講,要搞讀懂js代碼,首先就要弄清楚js的做用域鏈,下面看一份代碼數組

function test(a){
            var b = a+2;
            var bar = function(c){
                console.log(a,b,c);
            }
            bar(b*a);
        }
        test(2);

這個函數中 咱們定義了一個test 函數,該函數中咱們能夠看出做用域鏈層層嵌套,首先是全局的,而後是test,而後是bar,在上下文執行棧中,全局執行環境會被放在棧底,而咱們的test函數會第二我的入棧,而後發現裏面嵌套了一個bar函數,又會將bar函數入棧瀏覽器

咱們用一個數組來比做執行上下文棧,那麼上面代碼能夠寫成閉包

        var Esc = [];
        Esc.push(gloabContext);//首先全局上下文先壓入棧底
        Esc.push(test); //其次是test的執行上下文
        Esc.push(bar);//最後入棧的是bar
        Esc.pop(bar);//而後bar 執行完以後就彈出 變量回收,閉包變量會存在
        Esc.pop(test);// test 彈出
        Esc.pop(gloabContext);// 瀏覽器或者也頁面關閉時 全局執行環境清空

上面就是一個靜態做用域的執行流程,也就是說做用域只跟當前函數變量代碼聲明時有關,下面再看一個例子,函數

var test = "global test";
        function foo(){
            var test = "local test";
            var bar = function(){
                console.log(test);
            }
            bar();
        }
      foo() //輸出 localtest

上面輸出的是local test ,由於當今入bar的執行上下文的時候,test 會在上一層做用域鏈foo的執行上下文中找到,也就是在做用域創建階段,bar函數和test變量會綁定在foo的執行上下文環境中,咱們再看一個例子spa

var value = 1;

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

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

bar();//輸出爲1

上面的代碼,若是按照常規的思惟,咱們就會想到value 會在bar中找到,應該輸出2,但這種想法是錯的,由於做用域綁定在代碼書寫的時候就肯定了,也就是說,當foo函數在全局上下文執行環境書寫時,就跟全局value一塊綁定了,因此看成用域鏈向上查找的時候code

就會找到全局value,而不是bar中的,因此,js中的做用域鏈是在書寫代碼時肯定的,而不是在執行的時候肯定的。blog

咱們再看一到題目,作用域

var test = "global test";
        function foo(){
            var test = "local test";
            var bar = function(){
                console.log(test);
            }
            bar();
        }
      foo()
    var test1 = "global test1";
        function foo1(){
            var test1 = "local test1";
            var bar = function(){
                console.log(test1);
            }
            return bar;
        }
        foo1()();

這兩段代碼輸出是同樣的嗎,若是同樣,那麼他們有不一樣點嗎?io

相關文章
相關標籤/搜索