views:

513

answers:

4

Is it possible to simulate constants in Javascript using closures? If so, can you please furnish me with an example?

+2  A: 

You can create read-only, named constants with the const keyword (Implemented in JavaScript 1.5).

CMS
A quick Google shows this is *not* supported in all browsers... particularly, (yep, you guessed it), IE7 or IE8b2.
kquinn
Kind of makes your other comments moot!
Gary Willoughby
Who cares that IE doens't support this. People develop their JS in FireFox. So they will notice there that stuff doesn't work as expected and then fix it before releasing it. So there will never be a problem in IE.
Pim Jager
Firefox supports this, but IE - doesn't. So writing such code isn't a good practice.
Andrew Dashin
+5  A: 

Firefox and Chrome both support the const keyword. IE does not. So if you need constants and don't need to support IE, const isn't a bad choice. Keep in mind though, neither browser produces a runtime error when a value is assigned to a const; the values merely remains unchanged.

Otherwise, you must use functions to define constants that cannot be modified:

function PI() { return 3.14159; }

var area = radius*radius * PI();

Of course, you could just write code that never modifies certain variables, and maybe establish a naming scheme for such variables such that you recognize that they will never need to be modified...

// note to self: never assign values to variables utilizing all-uppercase name
var PI = 3.14159;

Another option for "simulating" constants would be to use the property definition functionality available in some browsers to define read-only properties on an object. Of course, since the browsers supporting property definitions don't include IE, that doesn't really help... (note that IE8 does support property definitions after a fashion... but not on JavaScript objects)

Finally, in very contrived scenarios you might use function arguments as constants (perhaps this is what you were thinking of when you suggested closures?). While they behave as variables, they remain scoped to the function in which they are defined and cannot therefore affect the values held by variables with the same name outside of the function in which they are modified:

var blah = 3;
var naw = "nope";
(function(blah, naw)
{
  blah = 2;
  naw = "yeah";
  alert(naw + blah); // "yeah2"
})(blah, naw);

alert(naw + blah); // "nope3"

Note that something similar to this is commonly used by jQuery plugins, but for the opposite reason: jQuery code is usually written using the $ shorthand to refer to the jQuery object, but the library is intended to continue working even if some other code redefines that symbol; by wrapping library and plugin code in anonymous functions with a $ parameter and then passing in jQuery as an argument, the code is isolated from changes other libraries might make to the value of $ later on.


See also: Are there constants in Javascript?

Shog9
Of course, for your first example, you could just set PI to be a *different* function—there's no real enforced const-ness there.
Miles
Yes; JavaScript tends to make overriding code extremely easy if that is your intention. However, if your intention is to prevent unintentional assignment of a new value to a constant, the function method would serve.
Shog9
-1: Same reason as Miles gives. Also why pass in blah and naw when you don't even use their values. Just define new local variables.
trinithis
Um, same reply I gave to Miles then. Also... did you miss the "very contrived scenario" bit? That last technique is *only* useful when you want a name to remain under your control for a given bit of code *regardless* of what other code does elsewhere... For example, a jQuery plugin that wants to refer to jQuery using `$` even if some other library redefines that symbol to mean something else. If you don't have to worry about code you don't control, then it makes no sense.
Shog9
A: 

Yes, you should see this answer:

http://stackoverflow.com/questions/130396/are-there-constants-in-javascript/131286#131286

Pim Jager
-1: The correct answer is NO, not yes.
trinithis
A: 

This is as far as i got:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
    <head>
     <script type="text/javascript">
      function Scope()
      {
       return function()
       {
        return {Constant: 1}; //Object literal
       };
      }
      var Scope = Scope();
     </script>
    </head>
    <body>
     <script type="text/javascript">
      document.write(Scope().Constant + "<br />");

      //The following line of code has no effect and fails silently.
      Scope().Constant = 6;

      document.write(Scope().Constant + "<br />");
     </script>
    </body>
</html>

This approach allows me to extend the scope to have more than one constant member variable by extending the object literal.

Gary Willoughby
The first <script> block is functionally equivalent to: function Scope() { return {Constant: 1}; }
Miles
For the second <script> block, the line you commented doesn't actually fail silently. What it does is modify the object returned from the Scope() invocation, which is then thrown away; each time Scope() is called, it returns a new object which was constructed from the literal.
Miles
thanks, i'm learning more. You think you know javascript then along comes a feature that becomes popular and you think i must revisit this language and realise you know nothing. lol.
Gary Willoughby