一、視頻
閉包視頻講解:蛋老師視頻
二、未閉包
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i++);
}, 4000)
}
console.log(i);//5
//輸出結果為:5,5,6,7,8,9
{
var i = 0
setTimeout(() => {
console.log(i++);
}, 4000)
}
{
var i = 1
//放入任務隊列,等待同步任務執行后,再根據延遲時間執行
setTimeout(() => {
console.log(i++);
}, 4000)
}
{
var i = 2
//放入任務隊列,等待同步任務執行后,再根據延遲時間執行
setTimeout(() => {
console.log(i++);
}, 4000)
}
{
var i = 3
//放入任務隊列,等待同步任務執行后,再根據延遲時間執行
setTimeout(() => {
console.log(i++);
}, 4000)
}
{
var i = 4
//放入任務隊列,等待同步任務執行后,再根據延遲時間執行
setTimeout(() => {
console.log(i++);
}, 4000)
}
{
var i = 5
// i<5不成立,不繼續執行
}
// 執行全局console.log(i),輸出i等於5
// 4000ms延遲時間到,此時var=5(var沒有塊級作用域,除了function函數),所以輸出5次 console.log(i++)
// 輸出5,6,7,8,9
注:
1.setTimeout是異步,先放到任務隊列,同步執行完后,任務隊列里面再根據時間執行;
2.var沒有塊級作用域,所以for循環之后,i的值變為5,所以全局先輸出5
3.匿名函數可以訪問到外部i的值
三、采用閉包
for (var i = 0; i < 5; i++) {
(function (x) {
setTimeout(function () {
console.log(x++);
}, 400)
})(i)
}
console.log(i);//5
輸出結果:5 0,1,2,3,4
{
var i = 0
//i=0放入形參中,再執行里面的延遲函數,之后放入任務隊列,等待同步任務執行后,再根據延遲時間執行
(function (x) {
setTimeout(function () {
console.log(x++);
}, 400)
})(i)
}
{
var i = 1
//i=1放入形參中,再執行里面的延遲函數,之后放入任務隊列,等待同步任務執行后,再根據延遲時間執行
(function (x) {
setTimeout(function () {
console.log(x++);
}, 400)
})(i)
}
{
var i = 2
//i=2放入形參中,再執行里面的延遲函數,之后放入任務隊列,等待同步任務執行后,再根據延遲時間執行
(function (x) {
setTimeout(function () {
console.log(x++);
}, 400)
})(i)
}
{
var i = 3
//i=3放入形參中,再執行里面的延遲函數,之后放入任務隊列,等待同步任務執行后,再根據延遲時間執行
(function (x) {
setTimeout(function () {
console.log(x++);
}, 400)
})(i)
}
{
var i = 4
//i=4放入形參中,再執行里面的延遲函數,之后放入任務隊列,等待同步任務執行后,再根據延遲時間執行
(function (x) {
setTimeout(function () {
console.log(x++);
}, 400)
})(i)
}
{
var i = 5
// i<5不成立,不繼續執行
}
// 執行全局console.log(i),輸出i等於5,因為此時var=5,並且var不支持塊級作用域
//調用任務隊列里面的
/*(function (x) {
setTimeout(function () {
console.log(x++);
}, 400)
})(i)*/
// 依次輸出0,1,2,3,4