Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.7k views
in Technique[技术] by (71.8m points)

函数声明与闭包的问题

下面是这个闭包面试题一直一知半解的,对于输出的结果我是这么理解的,每次循环的时候执行一遍立即执行函数,然后往匿名函数里传入一个形参i,每次立即执行函数调用的时候产生的匿名函数都不是同一个,所以console.log所引用的变量i也不是同一个形参,所以每次定时器输出的都是当前循环时的i。

那是不是在每次for循环的过程中就产生了一个新的匿名函数呢,如果是这样的话就有另外一个问题了,function不是会声明提前吗,难道for循环真正执行之前已经提前声明了10个函数了?怎么从作用域或者内存的角度来解释为什么能得到这样的结果呢

function getNum() {
  for (var i = 0; i < 10; i++) {
    (function(i) {
        setTimeout(function() { console.log(i); }, 100 * i);
    })(i);
    }
}
//输出结果:0,1,2,3,4,5,6,7,8,9

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
  1. 你在for里定义的匿名函数是个函数表达式,不是函数声明语句,不存在声明提升。
  2. 如果换成函数声明试试呢?
function getNum() {
  for (var i = 0; i < 10; i++) {
      function temp(i) {
          setTimeout(function() { console.log(i); }, 100 * i);
      }
      temp(i)
    }
}
//输出结果:0,1,2,3,4,5,6,7,8,9
getNum();

结果没变。这是为啥呢?
再验证下:

function getNum() {
  // "use strict"; // 严格模式和非严格模式都试试
  console.log(1, typeof temp)
  for (var i = 0; i < 10; i++) {
    console.log(2, typeof temp)
    
    function temp(i) {
        //setTimeout(function() { console.log(i); }, 100 * i);
    }
    temp(i)
  }
  console.log(3, typeof temp)
}

getNum();

验证后再看下Javascript块级域内的函数声明提升


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...