【问题标题】:Implementing loop for var names for clickTags为clickTags的var名称实现循环
【发布时间】:2016-12-06 23:07:17
【问题描述】:

需要为横幅添加三个 clickTag,其名称为 clickTag1、clickTag2、clickTag3。现在代码如下所示:

for(var i = 1; i <= 3; i++) {
    document.getElementById('Destination_cta_' + i).addEventListener('click', function() {
        window.open(clickTag2, '_blank'); //here I want clickTag look like clickTag + i, but its not working.
    })
  }

所以问题是如何循环变量名称,所以我不需要像现在这样手动输入。

【问题讨论】:

  • 您正在寻找数组的奇迹。
  • 但是你也有臭名昭著的闭环错误。
  • 任何想法如何使它变得更好?
  • 了解数组。
  • @SLaks 我很好奇,闭环错误是什么

标签: javascript loops clicktag


【解决方案1】:

解决此问题的最简单方法是使用Array

[, clickTag1, clickTag2, clickTag3].forEach(function(e, i) {
    document.getElementById('Destination_cta_' + i).addEventListener('click', function() {
        window.open(e, '_blank');
    })
})

另一种方法:如果您的clickTags 是全局变量,您始终可以将它们作为window 对象的全局属性访问:

for(var i = 1; i <= 3; i++) (function (i) {
    document.getElementById('Destination_cta_' + i).addEventListener('click', function() {
        window.open(window['clickTag' + i], '_blank')
    })
)(i)

额外的包装功能修复了上面cmets中提到的闭包错误。

【讨论】:

  • (new Array(n)).map((value, index) =&gt; { return 'clickTag' + (index + 1) }) 用于长度为 n 且元素为 clickTag1 的数组,clickTag2 ... clickTagn
  • 不...您将字符串误认为是变量。如果您将其设为动态窗口属性访问,则更接近正确,但即便如此,您也不知道 OP 是在处理全局变量还是局部变量。最重要的是, new Array 返回一个带有孔的数组,因此对其进行映射实际上不会做任何事情。您仍然有一个长度为 n 且没有值的数组。
【解决方案2】:

您想为此使用数组。数组是值的索引列表。

var clickTags = ["","www.nba.com","www.nhl.com","www.nfl.com"];
for(var i = 1; i <= 3; i++) {
    document.getElementById('Destination_cta_' + i).addEventListener('click', function() {
        window.open(clickTags[i], '_blank'); //here I want clickTag look like clickTag + i, but its not working.
    })
}

请注意,由于您在 1 而不是 0 开始循环,因此我为 clickTags 数组的索引 0 添加了一个空白条目。

【讨论】:

  • 这些变量的值如 clickTag1 = "nba.com" 等。现在它只打开一个空白页面。有什么想法吗?
  • 那是因为闭环错误。
  • 要么^^^,要么看我的编辑,如果你真的不懂数组...
  • 正如@SLaks 所说,在阅读了他的引用链接后,他看起来是正确的......使用我发布的当前代码,您的所有点击事件都将打开 www.nfl。 com。您需要研究闭环错误以修复该错误。
  • 这个解决方案仍然受到关闭错误的影响——请看我在下面发布的内容:)
【解决方案3】:

为什么它目前没有按照您的预期工作:

for (var i = 1; i <= 3; i++) {
  // During your first loop there is a local variable `i` whose value is 1
  document.getElementById('Destination_cta_' + i)
    // Here you pass an anonymous function as the second argument to addEventListener
    // This creates a closure, which means the function's context includes variables
    // that were in scope when it was created. Right now we have the `for` loop's variable
    // `i` in the current scope, so the function keeps a *reference* to that variable.
    .addEventListener('click', function() {
     
      // When this get executed in the future, the function has to know about the variable `i`,
      // and thankfully there is a reference to it in this function's closure. But remember that
      // the for loop executed 3 times, using that same variable. That means that every function
      // was created with a closure that is keeping a reference to the same variable, whose final 
      // value after the loop finished, was 4. 
      window.alert('clickTag' + i);  // Will always alert 'clickTag4' no matter which is clicked
  })
}
<div id="Destination_cta_1">1</div>
<div id="Destination_cta_2">2</div>
<div id="Destination_cta_3">3</div>

如何解决这个问题?

确保每个addEventListener 调用都在其自己的闭包中获取具有正确值的函数。做到这一点的方法是使用一个立即调用的函数表达式,您可以将所需的值传递给该表达式:

for (var i = 1; i <= 3; i++) {
  var element = document.getElementById('Destination_cta_' + i)

  element.addEventListener('click', (function(index) {
    // This function is now a closure with a reference to index
    return function() { 
      window.alert('clickTag' + index);
    }
  })(i)) // calling the anonymous function with the current value of `i` binds that value
         // to the function's scope
}
<div id="Destination_cta_1">1</div>
<div id="Destination_cta_2">2</div>
<div id="Destination_cta_3">3</div>

【讨论】:

    猜你喜欢
    • 2014-03-02
    • 1970-01-01
    • 2014-02-25
    • 1970-01-01
    • 2023-01-21
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多