jquery - javascript - How to make this code work? -
this question has answer here:
code gives me: b c
when click on b c shows me last 1 "vodka". want "martin" (for a), "lindsay"(for b), "vodka" (for c)
please me on example.
myarray = [ { letter: "a", brand: "martin" }, { letter: "b", brand: "lindsay" }, { letter: "c", brand: "vodka" } ]; var list = ''; (var = 0; < myarray.length; i++) { list += "<br>" + myarray[i].letter; new_info = myarray[i].link; (function(new_info) { $(this).click(function(){ //this - refers or b or c $('#box2').text(new_info); }); }).call(this, myarray[i]) } $('#box1').append(list);
edit:
said wasn't going write code you... well, did: this fiddle you're looking for. solved issue context (this
), closure issues , implied globals. still needs lot of work, fiddle shows has been saying: $(this)
does not, cannot , never point string constant "a", or "b"
.
sorry this, code full of problems, address specific issue you're asking here.
inside loop, you're assigning click handler that, looks this:
function() { $('#box2').text(new_info); }
where new_info
variable declared in higher scope. far, good. problem is, function object you're creating doesn't have own copy of whatever value variable (new_info
) happened hold when function created. instead, function references variable. when of functions invoked $('#box2').text(new_info)
resolved $('#box2').text("whatever value new_info holds when function called")
, not $('#box2').text("whatever value new_info holding when function created")
. can give each callback access a copy adding second function code:
$(this).click((function(currentnewinfo) { return function() { $('#box2').text(currentnewinfo); } }(new_info)));
what i'm doing here creating function, takes argument, , calling immediately. pass new_info
argument, value of currentnewinfo
new_info
holds @ time (aka copy)
function called (iife - or invoked function expression) returns actual callback. in callback, don't reference new_info
, argument of iife: currentnewinfo
.
because each function has own scope, variable enclosed (hence name closure), , cannot accessed or altered outside. thing can still access currentnewinfo
variable function iife returned.
perhaps worried name-conflicts (each callback create uses references currentnewinfo
), that's not case: each callback created separate function, , therefore has access different scope. it's not possible have name conflict between scopes don't access each other... make things really simple understand:
where /\ , /\ || || return function() scope of iife
so closures have access function's scope after returns. scope has precedence when comes resolving expression value. understand better, here's similar diagram show how js resolves expressions:
each pink "outer environment record" scope of function (closure scope of function has returned or function being called). last environment either global object, or null (in strict mode). that's there it.
honestly, closures tricky head round @ first, once grasp tried explain here, they're great fun.
check link can go on explain use cases , benefits , ways nested closures work, i'd end writing book. link posted great job @ explaining how closures work using rather silly drawings. may seem childish, helped me lot when trying grasp concept of lambda functions, closures , scopes out-living function-call. diagrams above taken page linked to, explains concepts bit more in-depth, still think simple, crude drawings pretty self explanatory.
other issues:
pointed out: "what expecting this
reference". looking @ snippet, this
reference global object (window
), attaching same/similar event handler window
doesn't make sense if ask me.
global variables evil, implied globals more so. can't see new_info
, nor myarray
being declared anywhere. way js resolves expressions tad unfortunate , falls creating global variables, without peep:
var bar = 666;//global, evil function createglobal() { var local = 2; foo = bar * local; } createglobal();
let's @ foo
:
js in createglobal scope: var local declared, , assigned 2. foo used, , assigned bar*local || || \\=>found in current scope, resolves 2 || || || \\=>found in global scope, resolves 666 || || ||=> js looks foo declaration in function scope first, not found || ||=> moves 1 scope (either higher function, or global scope) || \\=>global scope, foo not found, create foo globally! - hence, implied global \\ \\=>foo can resolved global variable, value undefined
excessive dom queries: event-handler callbacks so:
$('#box2').text(new_info);
this ($('#box2')
) same writing document.getelementbyid('#box2')
. practically english. think this: each time client clicks on $(this)
- whatever may be, you're accessing dom, , scanning element given id. why not once , use reference kept in memory change text. saves countless dom queries.you could use variable, or (in light of explained closures), closure:
var list = (function(box2, list, i) {//list & arguments, local scope, (i = 0; < myarray.length; i++) { list += "<br>" + myarray[i].letter;//<-- don't know why use //new_info = myarray[i].link; no need var $(this).click((function(new_info) {//new_info closure var return function () {//box2 references dom element, kept in memory reduce dom querying box2.text(link); }; }(myarray[i].link));//instead of new_info, pass value here } return list;//return string, assign outer variable }($('#box2'), ''));//query dom here, pass reference argument
Comments
Post a Comment