在學(xué)習(xí)寫輪播圖,還有學(xué)習(xí)《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
超級簡單是吧,但是要明白這中間的過程是什么,一步步來:
- 定義了一個變量fn和一個函數(shù),函數(shù)的內(nèi)容是
var result = 1; ...
,將變量fn指向這個函數(shù)
算了還是稍微畫個圖吧
對于棧和堆還不是很了解
為了等下更好理解函數(shù),這里的所有變量的值都當(dāng)做引用類型,所有的變量都是指向,給變量加上()相當(dāng)與執(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
- 將fn指向function(){var result = []...}
- 執(zhí)行fn所指向的function,新建result,將result指向一個Array,將result[0]指向function(){return i;},result[1]指向另一個function(){return i;},result[2]也一樣,雖然內(nèi)容一樣,不過這是不同的三個函數(shù),返回result,這時result1指向result
- 執(zhí)行result[0]所指向的函數(shù),返回i,但是arguments沒有,自己本身沒有定義,所以根據(jù)作用域鏈,只能在上級函數(shù)中找到,這時候函數(shù)中的語句已經(jīng)在第二步執(zhí)行完畢,i=3,所以返回了3,result2就指向3,這下重點來了,這里就算是閉包的部分了,通常來說,當(dāng)fn所指向的函數(shù)執(zhí)行完畢后會銷毀其活動對象,也就是定義的result,i等等,但是因為返回的result的詞法作用域(lexcical scope)是在定義時確定的,(先不管with和trycatch),要用到i,這時就保留了上級函數(shù)的活動對象,以便于result所指向的函數(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é)果
[0, 1, 2] 0 1 2
這次在result所指向的的函數(shù)后面加上了(),在result2,3,4后面取消了()
- 略
- 執(zhí)行fn指向的函數(shù),和上一次相同,定義函數(shù),但是立即執(zhí)行,這時result[0]就指向這個函數(shù)的的返回值,第一此循環(huán)i=1,執(zhí)行一次function(){return i;},同樣向上找到i=1,返回1,result[0]就指向1,后面的相同,然后返回result
- 這時候fn()就指向了在堆中的那個Array,result也就指向那個Array
- 打印
這下稍微難點的
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
- 略
- 執(zhí)行fn指向的函數(shù),和上一次相同,定義函數(shù),立即執(zhí)行,這時result[0]指向函數(shù)function(){return i};
,result[1]指向另一個function(){return i;},result[2]同上,返回result,是不是感覺和第一次一樣,但是等下判斷i的值就不一樣了 - 執(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 - 打印