【问题标题】:Passing parameters in Javascript onClick event在 Javascript onClick 事件中传递参数
【发布时间】:2011-03-30 13:39:31
【问题描述】:

我正在尝试在 onclick 事件中传递参数。下面是一个示例代码:

<div id="div"></div>

<script language="javascript" type="text/javascript">
   var div = document.getElementById('div');

   for (var i = 0; i < 10; i++) {
       var link = document.createElement('a');
       link.setAttribute('href', '#');
       link.innerHTML = i + '';
       link.onclick=  function() { onClickLink(i+'');};
       div.appendChild(link);
       div.appendChild(document.createElement('BR'));
       }

   function onClickLink(text) {
       alert('Link ' + text + ' clicked');
       return false;
       }
    </script>

但是,每当我点击任何链接时,警报总是显示“点击链接 10”!

谁能告诉我我做错了什么?

谢谢

【问题讨论】:

    标签: javascript closures


    【解决方案1】:

    发生这种情况是因为一旦调用函数, i 就会向上传播范围。您可以使用闭包来避免这个问题。

    for (var i = 0; i < 10; i++) {
       var link = document.createElement('a');
       link.setAttribute('href', '#');
       link.innerHTML = i + '';
       link.onclick = (function() {
          var currentI = i;
          return function() { 
              onClickLink(currentI + '');
          }
       })();
       div.appendChild(link);
       div.appendChild(document.createElement('BR'));
    }
    

    或者如果你想要更简洁的语法,我建议你使用 Nick Craver 的解决方案。

    【讨论】:

    • 对这个 Jamie 的精彩描述!
    • 哈!因为我们在 link.onclick = 的 RHS 上定义的 closure 可以访问包含它的函数,这意味着里面的 i 是对外部 i 的引用,而不是复制的值(与普通的按值传递传递参​​数一样)! :)) 迷人的。我终于明白了:D
    【解决方案2】:

    试试这个:

    <div id="div"></div>
    
    <script language="javascript" type="text/javascript">
       var div = document.getElementById('div');
    
       for (var i = 0; i < 10; i++) {
           var f = function() {
               var link = document.createElement('a');
               var j = i; // this j is scoped to our anonymous function
                          // while i is scoped outside the anonymous function,
                          //  getting incremented by the for loop
               link.setAttribute('href', '#');
               link.innerHTML = j + '';
               link.onclick=  function() { onClickLink(j+'');};
               div.appendChild(link);
               div.appendChild(document.createElement('br')); // lower case BR, please!
           }(); // call the function immediately
       }
    
       function onClickLink(text) {
           alert('Link ' + text + ' clicked');
           return false;
       }
    </script>
    

    【讨论】:

      【解决方案3】:
      link.onclick = function() { onClickLink(i+''); };
      

      是一个闭包,存储了对变量i的引用,而不是创建函数时i持有的值。一种解决方案是将for 循环的内容包装在一个函数中:

      for (var i = 0; i < 10; i++) (function(i) {
          var link = document.createElement('a');
          link.setAttribute('href', '#');
          link.innerHTML = i + '';
          link.onclick=  function() { onClickLink(i+'');};
          div.appendChild(link);
          div.appendChild(document.createElement('BR'));
      }(i));
      

      【讨论】:

      • 我认为你有一些括号不平衡。最后一行应该是})(i);吗?
      • 这行得通,省略外括号也是如此,但这是“Crockford-approved”样式:stackoverflow.com/questions/939386/…
      【解决方案4】:

      发生这种情况是因为它们都引用了 same i 变量,该变量在每个循环中都会发生变化,并在循环结束时保留为 10。您可以使用这样的闭包来解决它:

      link.onclick = function(j) { return function() { onClickLink(j+''); }; }(i);
      

      You can give it a try here

      或者,将this 设为您在该处理程序中单击的链接,如下所示:

      link.onclick = function(j) { return function() { onClickLink.call(this, j); }; }(i);
      

      You can try that version here

      【讨论】:

      • 要明确一点:您是否返回了接受参数 j 的匿名函数的声明,同时您也传递了实际参数? ((i))
      • @dierre - (i) 调用function(j),参数为当前i,触发它返回复制值在闭包中的函数,不再连接到i,有意义吗?
      • 我说的好像一样,但我不确定:对我来说 function(j) { return function() { onClickLink(j+''); }; }MyAnonymFunction(j)。我看到的是 link.onclick = MyAnonymFunction(i);
      • @dierre - 使用反勾号(波浪号键)作为注释代码 :) 我不确定如何以不同的方式描述它,您正在调用返回另一个匿名函数的匿名函数,但使用一个不同的变量,因为它来自不同的闭包(外部函数)。
      • 我刚刚发现了 Ctrl-K 快捷键,但不适用于 cmets。顺便说一句,我明白了。对不起我的英语:)
      【解决方案5】:

      或者你可以使用这一行:

       link.setAttribute('onClick', 'onClickLink('+i+')');
      

      而不是这个:

      link.onclick=  function() { onClickLink(i+'');};
      

      【讨论】:

        【解决方案6】:

        另一种简单的方法(可能不是最佳做法)但效果很好。使用 javascript 动态构建元素(hyperLink 或 Button)的 HTML 标记,并且还可以传递多个参数。

        // variable to hold the HTML Tags 
        var ProductButtonsHTML  ="";
        
        //Run your loop
        for (var i = 0; i < ProductsJson.length; i++){
        // Build the <input> Tag with the required parameters for Onclick call. Use double quotes.
        
        ProductButtonsHTML += " <input type='button' value='" + ProductsJson[i].DisplayName + "'  
        onclick = \"BuildCartById('" + ProductsJson[i].SKU+ "'," + ProductsJson[i].Id + ")\"></input> ";
        
        }
        
        // Add the Tags to the Div's innerHTML.
        document.getElementById("divProductsMenuStrip").innerHTML = ProductButtonsHTML;
        

        【讨论】:

          【解决方案7】:

          最好创建一个专用函数来创建链接,这样您就可以避免创建两个匿名函数。因此:

          <div id="div"></div>
          
          <script>
            function getLink(id)
            {
              var link = document.createElement('a');
              link.setAttribute('href', '#');
              link.innerHTML = id;
              link.onclick = function()
              {
                onClickLink(id);
              };
              link.style.display = 'block';
              return link;
            }
            var div = document.getElementById('div');
            for (var i = 0; i < 10; i += 1)
            {
              div.appendChild(getLink(i.toString()));
            }
          </script>
          

          虽然在这两种情况下你最终都会得到两个函数,但我只是认为最好将它包装在一个语义上更容易理解的函数中。

          【讨论】:

            【解决方案8】:

            onclick 与 addEventListener。可能是一个偏好问题(IE>9)。

            // Using closures
            function onClickLink(e, index) {   
                alert(index);
                return false;
            }
            
            var div = document.getElementById('div');
            
            for (var i = 0; i < 10; i++) {
                var link = document.createElement('a');
            
                link.setAttribute('href', '#');
                link.innerHTML = i + '';
                link.addEventListener('click', (function(e) {
                    var index = i;
                    return function(e) {
                        return onClickLink(e, index);
                    }
                })(), false);
                div.appendChild(link);
                div.appendChild(document.createElement('BR'));
            }
            

            只使用一个普通的 data-* 属性是如何邻接的,不像闭包那么酷,但是..

            function onClickLink(e) {       
                alert(e.target.getAttribute('data-index'));
                return false;
            }
            
            var div = document.getElementById('div');
            
            for (var i = 0; i < 10; i++) {
                var link = document.createElement('a');
            
                link.setAttribute('href', '#');
                link.setAttribute('data-index', i);
                link.innerHTML = i + ' Hello';        
                link.addEventListener('click', onClickLink, false);
                div.appendChild(link);
                div.appendChild(document.createElement('BR'));
            }
            

            【讨论】:

              【解决方案9】:

              这将在 JS 中工作而无需与 HTML 耦合:

              document.getElementById("click-button").onclick = onClickFunction;
              
              function onClickFunction()
              {
                  return functionWithArguments('You clicked the button!');
              }
              
              function functionWithArguments(text) {
                  document.getElementById("some-div").innerText = text;
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2015-09-07
                • 2019-12-27
                • 2017-02-05
                • 1970-01-01
                • 2017-07-24
                • 1970-01-01
                相关资源
                最近更新 更多