0

I read through Explaining Javascript Scope and Closures

but I can't seem to get the following code to work. As you can see I have tried a lot of variations, and can't pass in the current value to a function that will be called later.

I want the alert to read "START" not "END" when the div is clicked... help?

var someString = "START";
document.getElementById('elem1').onclick = function(){
   return function(someString){
           alert(someString);
     }();
  };

document.getElementById('elem2').onclick = function(){
           alert(someString);
  };

document.getElementById('elem3').onclick = function(){
    alert(new String(someString));
};

document.getElementById('elem4').onclick = function(someString){
   return function(someString){
           alert(someString);
     }();
  };

document.getElementById('elem5').onclick = function(someString){
   return function(){
           alert(someString);
     }();
  };


document.getElementById('elem6').onclick = function(){
    var newSomeString =someString; 
    alert(newSomeString);
};


var someString = "END";
<body>
<div style="background-color='yellow';display:block;" id="elem1">1</div>
<br>
<div style="background-color='red';display:block;" id="elem2">2</div>
<br>
<div style="background-color='blue';display:block;" id="elem3">3</div>
<br>
<div style="background-color='green';display:block;" id="elem4">4</div>
<br>
<div style="background-color='orange';display:block;" id="elem5">5</div>
<br>
<div style="background-color='pink';display:block;" id="elem6">6</div>
<br>
</body>
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Roman Rekhler
  • 475
  • 6
  • 6

2 Answers2

0

JavaScript is functionally-scoped. You are attaching callback functions to all of those listeners but they are not executed until the callback is actually fired. By that point, you have changed the value of the message.

If you want to encapsulate the scope, you have several options. You could wrap the logic that is attaching the listeners in an IIFE, for one.

You could also just move the work to a function that you run when you're ready. Here's an example of that:

var someString = "START";

setListener();

function setListener(message) {
    message = message || someString;
    document.getElementById('elem1').onclick = function(){
        alert(message);
    };
}

var someString = "END";

http://jsfiddle.net/dh2hr2px/1/

Community
  • 1
  • 1
Antiga
  • 2,264
  • 1
  • 20
  • 28
0

The problem is when the code gets executed. When you execute the click, you have already changed its value. The below code will work.

var someString = "START";
function createCallback() {

    var newSomeString = new String(someString);
    return function() {
       alert(newSomeString);
    }
}

document.getElementById('elem').onclick = createCallback();

someString = "END";
<body>
<div style="background-color='pink';display:block;" id="elem">6</div>
<br>
</body>
user1545858
  • 725
  • 4
  • 21
  • thanks!.. this worked, but the createCallBack() function isn't necessary. The key i guess is creating a new variable within the scope of the new function, whose value gets set out of the inside function. Though, why this doesn't just pass a handle to the initial someString I don't know. In java, I'd use new String to make it completely new... the following works for me `document.getElementById('elem7').onclick = function(){ var newSomeString = someString; return function() { alert(newSomeString ); } }();` – Roman Rekhler Feb 10 '15 at 23:29
  • @RomanRekhler, yeah, the createCallBack function is just my personal preference. You are right on both counts. If I remember correctly, strings are primitive objects in JS. As with Java, primitives are not referenced. – user1545858 Feb 10 '15 at 23:42
  • @RomanaRekhler not sure if you noticed my answer (which actually came before this one), but I explained the answer to that question and gave you an example. I also fixed your background color css while I was there. Not sure why I bother to answer sometimes. :) – Antiga Feb 11 '15 at 00:15