局部变量和参数之间的区别

问题描述:

function addLinks() { 
    for (var i=0, link; i<5; i++) { 
     link = document.createElement("a"); 
     link.innerHTML = "Link " + i; 
     link.onclick = function (num) { 
      return function() { 
       alert(num); 
      }; 
     }(i); 
}} 

为每个链接创建闭包;每个封闭都参考它创建的范围。由于参数num已在每个循环上更新,因此在第一个链接上的click上应该提示4。不是吗?局部变量和参数之间的区别

+0

参数num从不更新,它是每个调用的新变量。 – bfavaretto 2013-04-07 16:06:25

根本不是,每个函数调用得到num变量的新副本,以便第一个链接应该提醒0

如果你真的想拥有所有的回调共享相同的变量...然后只是有它们共享相同的变量(包装“民”的东西正是要避免这个问题,让回调是独立的):

//now all the inner closures use the same "i" variable 
//since the variable gets mutated by the for loop 
//all links are going to print "5" after the loop ends. 
for (var i=0, link; i<5; i++) { 
    link = document.createElement("a"); 
    link.innerHTML = "Link " + i; 
    link.onclick = function() { 
     alert(i); 
    }; 
} 

BTW,这只是发生,因为不像在其他语言,JS没有块循环索引的范围。因为如果你做了

var i; 
while(i < 5){ 
    //... 
    i++ 
} 
+1

你应该提到JS有一个功能范围,而'i'“活在”函数中,而不是循环中(也不是每次循环)。 – Joseph 2013-04-07 16:07:21

for循环的行为而由于你混淆两件事情:

  1. 函数的参数是函数的局部(用大“除非”,保存为2号)
    它们旨在以您选择的任何名称为函数的作用域别名一个对象(包括数组/函数)或值。
    目标是允许您将参数重命名为任何您想要的内容,以使内部代码变得有意义,而不管您从外部代码传入的参数是什么。
    这与范围无关。

  2. JS中的变量通过引用传递(如果它们是对象),如果它们是标量,则通过值传递。
    传递i到一个新的封闭的整点是,i被作为参数传递,而不是参考i,这是发生了什么,如果你不要” t包括关闭。

如果你要传递一个对象,该对象是什么了就可以了iobj.i += 1),然后再次关闭与否,每个功能将指向的i相同的值,因为他们” d都与同一个对象共享相同的参考。

对象参考通过,标量通过。
尽管技术上有字符串和数字对象,但只要您没有对它们进行任何面向对象的操作,它们就会直接转换为标量值。

var i = 3, 
    say_i = function() { console.log(i); }; 

var i = 3, 
    say_i = (function (val) { return function() { console.log(val); }(i)); 

第一个给出了一个参考i
say_i运行时,它实时查看i的值,并将其吐出到控制台中。

第二个已通过一个到返回的函数的外范围,别名为名称val
由于数字是按值传递的,而不是通过引用,所以val将永远等于相同的东西,除非从里面改变。

你也可以做到这一点相同的结果,如果你犯了一个功能一次,循环外:

var add_log = function (el, val) { el.onclick = function() { console.log(val); }; }, 
    i = 0, 
    el; 

for (; i < ........) { 
    el = .... 
    add_log(el, i); 
} 

i正在按值传递的,因此,所有的元素将在其范围表中的不同val因此,每个元素都会记录一个不同的数字。