jquery for循环有两种方法不同的索引

时间:2017-02-27 23:16:07

标签: javascript jquery arrays for-loop

这是我的html表单:

<form method="post" id="new_message" action="?action=changeRate">

              <div class="form-group">
                <label for="from" class="col-sm-2 control-label">From</label>
                <div class="col-sm-3">
                <select name="from" id="from" class="form-control">
                    <option value=""></option>
                    </select>
                </div>
              </div>

              <div class="form-group">
                <label for="to" class="col-sm-2 control-label">To</label>
                <div class="col-sm-3">
                <select name="to" id="to" class="form-control">
                    <option value=""></option>
                  </select>
                </div>
              </div>

              <div class="form-group">
                <label for="value" class="col-sm-2 control-label">Rate</label>
                <div class="col-sm-3">
                  <input type="text" class="form-control" name="ra" id="ra" placeholder="result" value="0">
                </div>
              </div>


                <p><input type="button" value="Submit" name="commit" id ="commit"/> or <a class="close" href="/">Cancel</a></p>
              </form>

这是我的jquery代码:

$('#to').on('change', function () {
                var fr = $('#from').val();
                var to = $('#to').val();
                for (i = 0; i < rates.length; ++i){
                if ((fr==rates[i].from) && to==rates[i].to) {

                    //the first i value is 0
                    console.log("i in if" + i);
                      $('input[name=ra]').val(rates[i].val);


                      $('#commit').click(function() {

                        //the second i value is always 3(same as array length)
                        console.log("i in commit " + i);

                      });
                  }
                }
              });

当我单击#commit按钮但是[i]索引增加到最大值时,我试图访问相同的[i]属性。如何在单击按钮时获得相同的索引?

3 个答案:

答案 0 :(得分:2)

你对i变量有一个闭包。这会导致i成为click回调触发时的最大值。

您可以尝试的是:

$('#to').on('change', function () {
            var fr = $('#from').val();
            var to = $('#to').val();
            for (i = 0; i < rates.length; ++i){
            if ((fr==rates[i].from) && to==rates[i].to) {

                //the first i value is 0
                console.log("i in if" + i);
                  $('input[name=ra]').val(rates[i].val);

                  (function(index) {
                    $('#commit').click(function() {

                    //the second i value is always 3(same as array length)
                    console.log("index in commit " + index);

                  });
                  })(i);

              }
            }
          });

答案 1 :(得分:1)

你的循环结束后,我将成为最大值,但你的点击处理程序仍然指的是同一个i。创建点击处理程序时,循环过程中i的值不会保存为#34;除非您通过函数传递它。

function makeCommitFunction(i) {
    return function () {
        console.log("i in commit " + i);
    };
}

$('#commit').click(makeCommitFunction(i));

答案 2 :(得分:1)

您正在for循环中附加您的点击处理程序。即使您确定if条件只是一次,这也是一个坏主意。将click处理程序移出change处理程序以避免多次绑定并更容易阅读。

在循环中找到值后,您可以使用变量来存储位于上部块中的范围值(或索引),如下例所示。如您所见,foundIdx将涵盖点击处理程序和更改处理程序。

或者,您可以使用.data()将索引(或该索引处的对象)附加到输入元素,以便您可以在任何需要的位置访问它。这类似val()但不可见。

您的代码失败,因为您无法保证在代码找到费率的同时点击按钮。它快得多了:)这就是为什么你需要在找到它之后立即存储它,然后在某个时间使用该值,因为它会在那里等待你。

封装点击处理程序的封闭是另一种存储&#39;将变量的值复制到新创建的范围时的值。但这不是正确的方法,因为#to元素上的每个更改都会导致新函数绑定到按钮的click事件。

示例:

// One of the options 1, 2, 3 can be used
var myInput = $('input[name=ra]');
var foundIdx = null; // option 1
var i = null; // option 3

$('#commit').click(function() {
  console.log("i (option 1) = " + myInput.data('i'));
  console.log("i (option 2) = " + foundIdx);
  console.log("i (option 3) = " + i);
  console.log("the rate : " + JSON.stringify(myInput.data('rate')));
});

$('#to').on('change', function() {
  var fr = $('#from').val();
  var to = $('#to').val();
  for (i = 0; i < rates.length; ++i) {
    if ((fr == rates[i].from) && to == rates[i].to) {
      myInput.val(rates[i].val);
      foundIdx = i; // option 1
      myInput.data('i', i); // option 2
      // option 3 is already there as long as the i is defined above
    }
  }
});

以下是完整的上述代码改写,推荐更改并使用ES2015更新:

// declare the input variable here in the upper scope
// to access it from the both handlers
const myInput = $('input[name=ra]');

$('#commit').click(function() {
  console.log("the rate : " + JSON.stringify(myInput.data('rate')));
  // do we want to use the index?
  // console.log("the index = " + myInput.data('idx'));
});

// we can assign the handler to 
// multiple elements in case if we want it to run
// on both from & to change
$('#from, #to').on('change', function() {
  const fr = $('#from').val();
  const to = $('#to').val();
  rates.forEach( (rate, idx) => {
    if (rate.from == fr && rate.to == to) {
      myInput.val(rate.val);
      myInput.data('rate', rate);
      // do we want to store the index?
      // myInput.data('idx', idx);
    }
  }
});