admin管理员组文章数量:1278789
For some reason no matter what, the pageNumber ends up being the last value in the loop for the loopCounter. Now I would understand that if I were directly using loopCounter in the closure itself, but I'm not. As you can see from the code below, I am creating a new variable within the closure to take the current value of loopCounter.
Only thing I can figure is (Assuming that javascript treats everything as a reference type) that pageNumber is taking the reference to loopCounter so no matter how many times I create a new pageNumber, it's always pointing at the loopCounter object. Therefore, whatever value loopCounter ends up with will be the value any pageNumber will point to.
How do I get it to not point at loopCounter but create a new pageNumber per iteration that holds the current loopCounter value?
for (var loopCounter = result.StartingPoint; loopCounter <= result.HighestPageCount; loopCounter++)
{
...
var newDiv = document.createElement('div');
...
//trying to remove the reference to loopCounter
var pageNumber = loopCounter;
newDiv.onclick =
function(event)
{ //Right here ---V
getResultUsingUrl(result.PagerPreLink + "&pageNumber=" + pageNumber);
};
...
}
SOLUTION
Thanks to a couple answers below:
function createClickMethod(loopCounter, link)
{
var pageNumber = loopCounter;
return function(event) { getResultUsingUrl(link + "&pageNumber=" + pageNumber); };
}
and I can call like:
newDiv.onclick = createClickMethod(loopCounter, result.PagerPreLink);
Or if I want to use jQuery... suggested below:
jQuery(newDiv).click
(
createClickMethod(loopCounter, result.PagerPreLink)
);
For some reason no matter what, the pageNumber ends up being the last value in the loop for the loopCounter. Now I would understand that if I were directly using loopCounter in the closure itself, but I'm not. As you can see from the code below, I am creating a new variable within the closure to take the current value of loopCounter.
Only thing I can figure is (Assuming that javascript treats everything as a reference type) that pageNumber is taking the reference to loopCounter so no matter how many times I create a new pageNumber, it's always pointing at the loopCounter object. Therefore, whatever value loopCounter ends up with will be the value any pageNumber will point to.
How do I get it to not point at loopCounter but create a new pageNumber per iteration that holds the current loopCounter value?
for (var loopCounter = result.StartingPoint; loopCounter <= result.HighestPageCount; loopCounter++)
{
...
var newDiv = document.createElement('div');
...
//trying to remove the reference to loopCounter
var pageNumber = loopCounter;
newDiv.onclick =
function(event)
{ //Right here ---V
getResultUsingUrl(result.PagerPreLink + "&pageNumber=" + pageNumber);
};
...
}
SOLUTION
Thanks to a couple answers below:
function createClickMethod(loopCounter, link)
{
var pageNumber = loopCounter;
return function(event) { getResultUsingUrl(link + "&pageNumber=" + pageNumber); };
}
and I can call like:
newDiv.onclick = createClickMethod(loopCounter, result.PagerPreLink);
Or if I want to use jQuery... suggested below:
jQuery(newDiv).click
(
createClickMethod(loopCounter, result.PagerPreLink)
);
Share
Improve this question
edited Jan 7, 2012 at 17:58
Lightness Races in Orbit
385k77 gold badges666 silver badges1.1k bronze badges
asked Aug 21, 2009 at 16:53
Programmin ToolProgrammin Tool
6,53711 gold badges52 silver badges69 bronze badges
2
- What is result.StartingPoint? – Nathan Taylor Commented Aug 21, 2009 at 16:56
- Eh a an object returned from a asynchronous method call. – Programmin Tool Commented Aug 21, 2009 at 17:20
5 Answers
Reset to default 9Like everyone else said, it's a scoping problem. Without using a JS library, you can do something like this:
newDiv.onclick = (function() {
var num = loopCounter;
return function(evt) {
console.log( num );
}
})();
You just need to create another closure around the value.
You are not creating a new pageNumber each time. You only have one. Scope in JavaScript does not extend beyond function-scope. Any "var" you declare in a function -- in or out of loops -- works exactly as it would had you declared it right at the top of the function.
http://javascript.crockford./code.html
Javascript closures store references to their variables, so all of your onclick handlers are using the same variable.
You need to capture the variable in an intermediate function, like this:
function buildClickHandler(pageNumber) {
return function(event) { //Create and return a new function
getResultUsingUrl(result.PagerPreLink + "&pageNumber=" + pageNumber);
}
}
Then, use that function to create onclick
handlers, like this:
for (var loopCounter = result.StartingPoint; loopCounter <= result.HighestPageCount; loopCounter++) {
//...
var newDiv = document.createElement('div');
newDiv.onclick = buildClickHandler(loopCounter);
}
Each call to buildClickHandler
creates a separate closure that has its own variable.
As an aside, consider using jQuery to do DOM manipulation; it's much easier than raw DOM APIs.
In your example, you could write
$('<div />').click(buildClickHandler(loopCounter));
Is result.StartingPoint really a primitive type, e.g. an actual Number type? If not, then perhaps what's happening is that you are getting a reference to that object and then the string concatenation is doing a type-coercion for you. Try this instead:
var pageNumber = new Number(loopCounter); // force coercion
The onclick closure will not maintain its scope, so it won't be able to access result.
Take a look at dojo.hitch for an easy and powerful solution, so that you can control its scope.
本文标签: javascriptPossible Access To Modified Closure Issue How To BeatStack Overflow
版权声明:本文标题:javascript - Possible Access To Modified Closure Issue... How To Beat? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741235609a2362950.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论