3

我正在尝试将“FROM”字段中的值复制到“TO”字段中。我的第一次尝试是这样的:

function updateToField(toField,fromField)
{
    toField.value = fromField.value}
}

function verifyFromToFields()
{
var inputs = getElementsByTagName("input");
for (var j = 0; j < inputs.length; j++)
{
    if (inputs[j].name.indexOf('FROM') != -1 && if (inputs[j+1].name.indexOf('TO') != -1)
        {
            var fromField = inputs[j];
            var toField   = inputs[j+1];
            fromField.onchange = function(){updateToField(toField,fromField)};
        }
}

该网站有几个 FROM-TO 对,这似乎只适用于“输入”数组中的最后一对。

然后我尝试了这个:

function updateToField(toField,fromField)
{
    toField.value = fromField.value}
}

function verifyFromToFields()
{
var inputs = getElementsByTagName("input");
for (var j = 0; j < inputs.length; j++)
{
    if (inputs[j].name.indexOf('FROM') != -1 && if (inputs[j+1].name.indexOf('TO') != -1)
        {
            var fromField = inputs[j];
            var toField   = inputs[j+1];
            fromField.onchange = function(){updateToField(toField,this)};
        }
 }

这样,当页面中的任何 FROM 字段被修改时,它都会被复制到页面上的最后一个 TO 字段。我认为这是我读过的关于参数作为值或参考的问题之一,但我无法弄清楚。这也是一个非常简化的代码版本,我实际上用 getElementsByClass 函数填充输入列表,并且必须搜索子节点。有没有人知道发生了什么?

4

3 回答 3

1

问题实际上与范围有关。发生的事情是您的函数(您分配给 的函数onchange)正在捕获变量toFieldfromField并且它们的值不断变化。我知道看起来你每次都在循环中重新声明了它们,但这不是 JS 的工作方式;循环中的连续行程共享一个范围,因此fromField每次都是相同的变量,您只是在每次迭代中为其分配一个新值。所以最后,你所有的函数都引用同一个fromField变量。该fromField变量自然包含您分配给它的最后一个值。

因此,当您最终调用所有这些函数时,它们都会做同样的事情,因为它们的所有fromFields(并且,按照相同的逻辑,toFields)都是相同的变量。这就解释了为什么只有最后一个输入有效;它们是您运行这些功能时所包含的内容fromFieldtoField

你可以通过引入一个中间函数来解决这个问题,因为函数确实会创建新的作用域。这样每次通过循环,你都会得到全新的变量。

function updateToField(toField,fromField)
{
   toField.value = fromField.value;
}

function verifyFromToFields()
{
  var inputs = getElementsByTagName("input");
  for (var j = 0; j < inputs.length; j++)
  {
    function(){
      if (inputs[j].name.indexOf('FROM') != -1 && if (inputs[j+1].name.indexOf('TO') != -1)
      {
          var fromField = inputs[j];
          var toField   = inputs[j+1];
          fromField.onchange = function(){updateToField(toField,fromField)};
      }
   }();
}
于 2013-01-23T13:10:59.887 回答
1

那个关闭,我不认为它意味着你认为它意味着什么。

这一行在这里:

     fromField.onchange = function(){updateToField(toField,this)};

意思是“分配给onchange一个函数,该函数将该字段的内容分配给更改时的任何toField内容

由于您只有一个变量toField,所有可变字段都将分配给它。

这会起作用:

var setOnChange = function(fromField, toField) {    
   fromField.onchange = function(){updateToField(toField,this)};
};

for (var j = 0; j < inputs.length; j++)
{
    if (inputs[j].name.indexOf('FROM') != -1 && if (inputs[j+1].name.indexOf('TO') != -1)
        {
            setOnChange(inputs[j], inputs[j+1]);
        }
 }

编辑:艾萨克可能对这个问题有更好的解释(尽管我不太喜欢他的解决方案)。

于 2013-01-23T13:11:30.133 回答
1

那是因为闭包是如何工作的。当您为onchange您创建的函数(为每个循环)分配一个新的匿名函数时,该函数调用updateToField,但toFieldandthis参数(或您传递的任何其他参数)的值不会绑定到“当前”循环,而是绑定到循环的最后一个值(这就是为什么只使用你的最后一个“TO”)。

onchange如果您在具有该功能的环境中运行,请尝试调用该属性,而不是为属性分配一个新功能Function.bind,或者如果您没有它,请编写一个。

这里是文档bind

所以你可以这样:

fromField.onchange = updateToField.bind(this, fromField, toField);

或者您可以使用Malvolio编写的其他方法。

于 2013-01-23T13:16:05.117 回答