Skip to main content
Ben Nadel at cf.Objective() 2010 (Minneapolis, MN) with: Mike Canonigo
Ben Nadel at cf.Objective() 2010 (Minneapolis, MN) with: Mike Canonigo ( @mcanonigo )

Dereferencing Javascript Variables - Revisiting

By on

As posted before I was having a very hard time getting dynamic onclick methods to call what I thought was a dereferenced variable. I was getting a lot of help and great suggestions on the CFTalk list, but one guy finally posted a link to:

http://calculist.blogspot.com/2005/12/gotcha-gotcha.html

This page discussed exactly the problem I was having, the reasons I was having it, and the solution. It's all about scoping of variables. The variable that I was alerting (in the dynamic onclick) was for the method (including every iteration of the FOR loop) and therefore each link pointed to it. In the solution below, the FOR loop is replaced with a repetative method call forces each variable scopes to be local.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Javascript Dynamic Variables</title>
<script type="text/javascript">

function TestClass( strName ){
this.Name = strName;
}

TestClass.prototype.AlertValue = function( anyValue ){
alert( this.Name + " is alerting: " + anyValue );
}


function Init(){
var objContentDiv = document.getElementById( "content" );
var objA = null;
var objTest = new TestClass( "Tester" );

// This runs the for loop using a LOCAL scope for each iteration.
(function loop( intI ){
var intX = intI;

if (intI < 10){

// Create new A element.
objA = document.createElement( "a" );

// Set A display properties.
objA.style.display = "block";
objA.style.backgroundColor = "#F8F8F8";
objA.style.border = "1px solid #333333";
objA.style.padding = "10px 10px 10px 10px";
objA.style.color = "#333333";
objA.style.marginBottom = "15px";

// Create text for the link.
objA.appendChild( document.createTextNode( "I should alert " + intX + " when clicked" ) );

// Set the href.
objA.setAttribute( "href", "##" );

// Set the onclick method.
objA.onclick = function(){ objTest.AlertValue( intX ) };

// Attach the A to the content.
objContentDiv.appendChild( objA );


loop(intI + 1);
}

})(0);

}


// Is the tester class available here (just testing).
alert( "objTest is of type: " + typeof(objTest));

</script>
</head>
<body onload="Init();">

<div id="content"></div>

</body>
</html>

Reader Comments

2 Comments

Hey thanks for this I'd be struggling with a similar problem all morning. JavaScript really is an ugly language, this solution seems a little strange but at least it works!

15,640 Comments

@Pete,

I would recommend looking into jQuery. It is an awesome Javascript framework that I have just started working with. One of the things it provides is an Each() method (this is common to many Javascript frameworks). But anyway, because the Each() method takes a function literal, it forces you to create a new local scope for each loop iteration. This, in and of itself, helps take care of many of the "referencing" issues.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel