Javascript'this'作为参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14480401/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 21:44:52  来源:igfitidea点击:

Javascript 'this' as parameter

javascriptfunctionparametersthis

提问by varrtto

I'm trying to copy the value from "FROM" fields into "TO" fields. My first attempt was this:

我正在尝试将值从“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)};
        }
}

The website has several FROM-TO pairs, and this only seem to work for the last pair in the "inputs" array.

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

Then I tried this:

然后我尝试了这个:

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)};
        }
 }

With this, when any FROM field in the page is modified, it's copied to the last TO field on the page. I think this is one of those issues I've read about parameters as value or reference, but I can't figure it out. Also this is a VERY simplified version of the code, I actually fill the inputs list with a getElementsByClass function and must search through childnodes. Does anyone have a clue on whats going on?

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

采纳答案by Malvolio

That closure, I do not think it means what you think it means.

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

This line here:

这条线在这里:

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

means "assign to onchangea function that assigns the contents of that fields to whatever toFieldis at the time of the change!

意思是“指定给onchange一个函数,该字段的内容分配给什么toField在改变的时候了!

Since you only have one variable toFieldall the changeable fields will be assigned to it.

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

This would work:

这会起作用:

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]);
        }
 }

EDIT: Isaac might have a better explanation of the problem (although I don't really like his solution).

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

回答by varrtto

The problem actually has to do with scope. What's happening is that your functions (the ones you assigned to onchange) are capturing the variables toFieldand fromFieldand their values keep changing. I know it looks like you've declared them anew each time through the loop, but that's not how JS works; consecutive trips through a loop share a scope, so fromFieldis the same variable each time through and you're merely assigning it a new value in each iteration. So at the end, all of your functions refer to the same fromFieldvariable. And that fromFieldvariable, naturally, contains the last value you assigned it.

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

So when you eventually call all of those functions, they all do the same thing, because all of their fromFields (and, by the same logic, toFields) are the same variable. So that explains why only the last inputs worked; they're what fromFieldand toFieldcontained when you ran the functions.

所以当你最终调用所有这些函数时,它们都做同样的事情,因为它们fromField的所有s(以及,按照相同的逻辑,toFields)都是同一个变量。所以这就解释了为什么只有最后的输入有效;他们在做什么fromField,并toField包含在您运行的功能。

You can fix this by introducing an intermediate function, since functions docreate new scopes. That way each time through the loop, you get brand new variables.

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

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)};
      }
   }();
}

回答by Lucas Gabriel Sánchez

That's is because of how closures work. When you assign the onchangefunction you create (for every loop) a new anonymous function that calls updateToField, but the value of the toFieldand thisparameters (or any other you are passing) are not bind to the "current" loop, instead that parameters are bind to the last value of the loop (that's why is only working with your last "TO").

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

Instead of assigning a new function to onchangeproperty try calling the Function.bindif you're running in an environment that has that or write one if you don't have it.

如果您在具有该功能的环境中运行,则不要将新功能分配给onchange属性,请尝试调用该功能,Function.bind如果没有,请尝试调用该功能。

Here are the documentation for bind

这里是文档 bind

So you can go like this:

所以你可以这样:

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

Or you can use the other approach that Malvoliowrote.

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