admin管理员组文章数量:1301594
I'm trying to copy the value from "FROM" fields into "TO" fields. My first attempt was 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,fromField)};
}
}
The website has several FROM-TO pairs, and this only seem to work for the last pair in the "inputs" array.
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?
I'm trying to copy the value from "FROM" fields into "TO" fields. My first attempt was 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,fromField)};
}
}
The website has several FROM-TO pairs, and this only seem to work for the last pair in the "inputs" array.
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?
Share asked Jan 23, 2013 at 13:03 varrttovarrtto 1012 gold badges3 silver badges11 bronze badges 5- 1 Less to do with this and pass-by-reference: More to do with closures. – kojiro Commented Jan 23, 2013 at 13:12
- @kojiro -- that's good advice but, by sheer chance, closures (and not this) are exactly what is screwing him up right now! – Michael Lorton Commented Jan 23, 2013 at 13:16
- @Malvolio that's what I was saying. :) – kojiro Commented Jan 23, 2013 at 13:32
-
@kojiro -- I pletely misunderstood what you mean: I thought you were suggesting that he should use closures instead of
this
, which I think is good advice, although here it would have made matters worse rather than better. – Michael Lorton Commented Jan 23, 2013 at 23:15 -
@Malvolio If there were a sane way to attach the relationship between fields (
$(fromfield).data("tofield", tofield)
) without using jQuery, usingthis
would bee dead simple. – kojiro Commented Jan 23, 2013 at 23:29
3 Answers
Reset to default 1That closure, I do not think it means what you think it means.
This line here:
fromField.onchange = function(){updateToField(toField,this)};
means "assign to onchange
a function that assigns the contents of that fields to whatever toField
is at the time of the change!
Since you only have one variable toField
all the changeable fields will be assigned to it.
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).
That's is because of how closures work. When you assign the onchange
function you create (for every loop) a new anonymous function that calls updateToField
, but the value of the toField
and this
parameters (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").
Instead of assigning a new function to onchange
property try calling the Function.bind
if you're running in an environment that has that or write one if you don't have it.
Here are the documentation for bind
So you can go like this:
fromField.onchange = updateToField.bind(this, fromField, toField);
Or you can use the other approach that Malvolio wrote.
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 toField
and fromField
and 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 fromField
is 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 fromField
variable. And that fromField
variable, naturally, contains the last value you assigned it.
So when you eventually call all of those functions, they all do the same thing, because all of their fromField
s (and, by the same logic, toField
s) are the same variable. So that explains why only the last inputs worked; they're what fromField
and toField
contained when you ran the functions.
You can fix this by introducing an intermediate function, since functions do create 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)};
}
}();
}
本文标签: functionJavascript 39this39 as parameterStack Overflow
版权声明:本文标题:function - Javascript 'this' as parameter - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741667073a2391376.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论