Javascript 为什么这段代码的行为像一个闭包?

Javascript 为什么这段代码的行为像一个闭包?,javascript,Javascript,据我所知,javascript中的for循环不会创建单独的闭包。那么,有人能解释一下为什么在下面的代码中,数组dogs没有填充对相同对象的两个引用吗?即{名称:'lunski',物种:'dog'} 我认为dogs[]中的两个数组元素都包含对动物的引用[2],但事实上,数组dogs将同时包含fluffy对象和lunski对象 编辑: 因此,尽管我知道情况并非如此,但看起来似乎正在创建一个闭包。但问题仍然是,为什么狗[]充满了与众不同的物体?你把概念搞混了。撇开闭包不谈,这完全是另外一回事,让我们看

据我所知,javascript中的for循环不会创建单独的闭包。那么,有人能解释一下为什么在下面的代码中,数组dogs没有填充对相同对象的两个引用吗?即{名称:'lunski',物种:'dog'}

我认为dogs[]中的两个数组元素都包含对动物的引用[2],但事实上,数组dogs将同时包含fluffy对象和lunski对象

编辑:
因此,尽管我知道情况并非如此,但看起来似乎正在创建一个闭包。但问题仍然是,为什么狗[]充满了与众不同的物体?

你把概念搞混了。撇开闭包不谈,这完全是另外一回事,让我们看看你问的问题

为什么在下面的代码中,数组dogs不是填充两个相同的数组 对象{name:'lunski',species:'dog'}

您正在将两个不同的对象动物[0]和动物[2]推入dogs数组-它们不是对动物对象本身的引用数组是对象,而是对单个动物元素中包含的对象的引用

因为这不是一个闭包,所以变量i没有固定到它设置的最后一个值

更新

我相信我终于理解了你想要问的问题——下面是一个答案,它展示了一个带闭包的匿名函数和一个不带闭包的匿名函数是如何与你的数组一起工作的

代码/小提琴创建了4个输入。第一个和第三个输入没有闭包,第二个和第四个输入有闭包。这些输入意味着点击它们有一个点击监听器,它们各自将动物[i]记录到控制台。请参阅下面示例中的注释以解释记录的值

var animals = [
    {name: 'fluffy', species: 'dog'}, 
  {name: 'miauw', species: 'cat'},
  {name: 'lunski', species: 'dog'}
  ];

var dogs = [];
for (var i = 0; i < animals.length; i++) {
  if (animals[i].species === 'dog') {
    // the first and third elements created in the loop have no closure
    // the variable i will be set to 2 because it has reached the end of its loop - it's value was not bound with function
    // therefore when you click on the input labeled "fluffy (no closure)" or lunski (no closure) they will log "undefined" to the console since animals[2] is undefined.
        e = document.createElement("input");
        e.value = animals[i].name + " (no closure)" ;
        e.addEventListener('click', function() {
          console.log(animals[i])}
        )
    document.body.appendChild(e);


    // the second and fourth elements created in the loop have closure
    // because the function is enclosed within a function
    // the variable i will be valid and set to what it is when the funtion runs 
    // Note: The exclamation point causes the outer function to be executed immediately - creating the event listener
    // therefore when you click on the input labeled "fluffy (closure)" or lunski (closure)
    // you will see the whole object in the console
    e = document.createElement("input");
    e.value = animals[i].name + " (with closure)" ;;
    !function(animals, i){
        e.addEventListener('click', function() {
          console.log(animals[i])}
        )
     }(animals, i)
    document.body.appendChild(e);
  }
};

我希望这会有所帮助。如果您有兴趣看到更多闭包示例,请看这篇

您认为这里为什么会涉及闭包?这段代码中没有闭包。这段代码中甚至没有任何函数不会创建引用,而是将值推送此处不涉及闭包,因为不涉及任何函数。狗的长度为2。您的代码显示,如果物种为狗,则将动物添加到狗的列表中。这正是它所做的。fluffy和lunski都是狗。我认为这两个数组元素都包含对动物的引用[I]在这种情况下,我是2。你为什么会这样想?你在推动物[i],所以它推动物[i],这取决于i的当前值,而不是最终值。你能想出一些例子吗?@suyesh-什么的例子?闭包?@suyesh-如果你有兴趣了解闭包,请参阅我文章的底部-我已经添加了一个链接。啊,它传递的是一个值,而不是一个引用。这回答了我的问题!那么它确实不会创建闭包,这使得sense@sjbuysse-即使您将一个对象分配给某个元素,并因此共享对该对象的引用,这也不是闭包。有关闭包的详细信息,请参阅引用的SO帖子。
var animals = [
    {name: 'fluffy', species: 'dog'}, 
  {name: 'miauw', species: 'cat'},
  {name: 'lunski', species: 'dog'}
  ];

var dogs = [];
for (var i = 0; i < animals.length; i++) {
  if (animals[i].species === 'dog') {
    // the first and third elements created in the loop have no closure
    // the variable i will be set to 2 because it has reached the end of its loop - it's value was not bound with function
    // therefore when you click on the input labeled "fluffy (no closure)" or lunski (no closure) they will log "undefined" to the console since animals[2] is undefined.
        e = document.createElement("input");
        e.value = animals[i].name + " (no closure)" ;
        e.addEventListener('click', function() {
          console.log(animals[i])}
        )
    document.body.appendChild(e);


    // the second and fourth elements created in the loop have closure
    // because the function is enclosed within a function
    // the variable i will be valid and set to what it is when the funtion runs 
    // Note: The exclamation point causes the outer function to be executed immediately - creating the event listener
    // therefore when you click on the input labeled "fluffy (closure)" or lunski (closure)
    // you will see the whole object in the console
    e = document.createElement("input");
    e.value = animals[i].name + " (with closure)" ;;
    !function(animals, i){
        e.addEventListener('click', function() {
          console.log(animals[i])}
        )
     }(animals, i)
    document.body.appendChild(e);
  }
};