變量,作用域鏈,指向函數(shù)與執(zhí)行函數(shù),閉包

在學習寫輪播圖,還有學習《js高級程序設(shè)計》中的執(zhí)行環(huán)境,變量,作用域,函數(shù),閉包時所想所感
下面我主要寫的是變量的指向,變量指向的函數(shù),變量指向的函數(shù)的執(zhí)行,變量指向的函數(shù)執(zhí)行時的作用域
先寫一個超級簡單的

function fn() {
    var result = 1;
    console.log(result);
    return result;
}
var result1 = fn;
var result2 = fn();
console.log(result1,result2);
//結(jié)果
1
function fn() {
      var result = 1;
      console.log(result);
      return result;
} 1

超級簡單是吧,但是要明白這中間的過程是什么,一步步來:

  1. 定義了一個變量fn和一個函數(shù),函數(shù)的內(nèi)容是var result = 1; ...,將變量fn指向這個函數(shù)

算了還是稍微畫個圖吧
對于棧和堆還不是很了解

測試圖片

為了等下更好理解函數(shù),這里的所有變量的值都當做引用類型,所有的變量都是指向,給變量加上()相當與執(zhí)行變量所指向的函數(shù)
還是簡單一點的

function fn() {
    var result = [];
    for (var i=0;i<3;i++) {
        result[i] = function() {
            return i;
        }
    }
    return result;
}
var result1 = fn();
var result2 = result1[0]();
var result3 = result1[1]();
var result4 = result1[2]();
console.log(result1,result2,result3,result4);
// 結(jié)果
[function...,function...,function...] 3 3 3
  1. 將fn指向function(){var result = []...}
  2. 執(zhí)行fn所指向的function,新建result,將result指向一個Array,將result[0]指向function(){return i;},result[1]指向另一個function(){return i;},result[2]也一樣,雖然內(nèi)容一樣,不過這是不同的三個函數(shù),返回result,這時result1指向result
  3. 執(zhí)行result[0]所指向的函數(shù),返回i,但是arguments沒有,自己本身沒有定義,所以根據(jù)作用域鏈,只能在上級函數(shù)中找到,這時候函數(shù)中的語句已經(jīng)在第二步執(zhí)行完畢,i=3,所以返回了3,result2就指向3,這下重點來了,這里就算是閉包的部分了,通常來說,當fn所指向的函數(shù)執(zhí)行完畢后會銷毀其活動對象,也就是定義的result,i等等,但是因為返回的result的詞法作用域(lexcical scope)是在定義時確定的,(先不管with和trycatch),要用到i,這時就保留了上級函數(shù)的活動對象,以便于result所指向的函數(shù)訪問,后面的兩個相同
  4. 打印出他們指向的值

再看一個

function fn() {
    var result = [];
    for (var i=0;i<3;i++) {
        result[i] = (function() {
            return i;
        })();
    }
    return result;
}
var result1 = fn();
var result2 = result1[0];
var result3 = result1[1];
var result4 = result1[2];
console.log(result1,result2,result3,result4)
// 結(jié)果
[0, 1, 2] 0 1 2

這次在result所指向的的函數(shù)后面加上了(),在result2,3,4后面取消了()

  1. 執(zhí)行fn指向的函數(shù),和上一次相同,定義函數(shù),但是立即執(zhí)行,這時result[0]就指向這個函數(shù)的的返回值,第一此循環(huán)i=1,執(zhí)行一次function(){return i;},同樣向上找到i=1,返回1,result[0]就指向1,后面的相同,然后返回result
  2. 這時候fn()就指向了在堆中的那個Array,result也就指向那個Array
  3. 打印

這下稍微難點的

function fn() {
    var result = [];
    for (var i=0;i<3;i++) {
        result[i] = (function(i) {
            return function() {
                return i;
            };
        })(i);
    }
    return result;
}
var result1 = fn();
var result2 = result1[0]();
var result3 = result1[1]();
var result4 = result1[2]();
console.log(result1,result2,result3,result4)
// 結(jié)果
[function...,function...,function...] 0 1 2
  1. 執(zhí)行fn指向的函數(shù),和上一次相同,定義函數(shù),立即執(zhí)行,這時result[0]指向函數(shù)function(){return i};
    ,result[1]指向另一個function(){return i;},result[2]同上,返回result,是不是感覺和第一次一樣,但是等下判斷i的值就不一樣了
  2. 執(zhí)行result1[0]指向的函數(shù)function(){return i;},先在自己的作用域中找,沒有,向上找,就是那個立即執(zhí)行的函數(shù)中找,arguments中有,這時的i是3嗎?顯然不是的,是立即執(zhí)行時傳入的i,因為返回的function(){return i;}在定義時傳入的0,所以這時的i為0,還記得剛才寫的,詞法作用域(lexcical scope)是在定義時確定的,return fuction(){}也可以理解為var anonymous = function(){}; return anonymous;同理后面返回1和2
  3. 打印
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容