I'm using class members to hold constants. E.g.:
function Foo() {
}
Foo.CONSTANT1 = 1;
Foo.CONSTANT2 = 2;
This works fine, except that it seems a bit unorganized, with all the code that is specific to Foo laying around in global scope. So I thought about moving the constant declaration to inside the Foo() declaration, but then wouldn't that code execute everytime Foo is constructed?
I'm coming from Java where everything is enclosed in a class body, so I'm thinking JavaScript might have something similar to that or some work around that mimics it.
All you're doing in your code is adding a property named CONSTANT with the value 1 to the Function object named Foo, then overwriting it immediately with the value 2.
I'm not too familiar with other languages, but I don't believe javascript is able to do what you seem to be attempting.
None of the properties you're adding to Foo will ever execute. They're just stored in that namespace.
Maybe you wanted to prototype some property onto Foo?
function Foo() {
}
Foo.prototype.CONSTANT1 = 1;
Foo.prototype.CONSTANT2 = 2;
Not quite what you're after though.
You must make your constants like you said :
function Foo() {
}
Foo.CONSTANT1 = 1;
Foo.CONSTANT2 = 2;
And you access like that :
Foo.CONSTANT1;
or
anInstanceOfFoo.__proto__.constructor.CONSTANT1;
All other solutions alloc an other part of memory when you create an other object, so it's not a constant. You should not do that :
Foo.prototype.CONSTANT1 = 1;
IF the constants are to be used inside of the object only:
function Foo() {
var CONSTANT1 = 1,CONSTANT2 = 2;
}
If not, do it like this:
function Foo(){
this.CONSTANT1=1;
this.CONSTANT2=2;
}
It's much more readable and easier to work out what the function does.
If you're using jQuery, you can use $.extend function to categorize everything.
var MyClass = $.extend(function() {
$.extend(this, {
parameter: 'param',
func: function() {
console.log(this.parameter);
}
});
// some code to do at construction time
}, {
CONST: 'const'
}
);
var a = new MyClass();
var b = new MyClass();
b.parameter = MyClass.CONST;
a.func(); // console: param
b.func(); // console: const
First, I recommend moving your class declaration inside of an IIFE. This cleans up the code, making it more self-contained, and allows you to use local variables without polluting the global namespace. Your code becomes:
var Foo = (function() {
function Foo() {
}
Foo.CONSTANT1 = 1;
Foo.CONSTANT2 = 2;
return Foo;
})();
The problem with assigning constants directly to the class as attributes is that those are writable. See this snippet:
var output = document.getElementById("output");
var Foo = (function() {
function Foo() {
}
Foo.CONSTANT1 = 1;
Foo.CONSTANT2 = 2;
return Foo;
})();
Foo.CONSTANT1 = "I'm not very constant";
output.innerHTML = Foo.CONSTANT1;
<div id="output"></div>
The best solution I have found is to define read-only properties for accessing the constants outside of the class.
var output = document.getElementById("output");
var Foo = (function() {
const CONSTANT1 = "I'm very constant";
function Foo() {
}
Object.defineProperty(Foo, "CONSTANT1", {
get: function() {
return CONSTANT1;
},
});
return Foo;
})();
Foo.CONSTANT1 = "some other value";
output.innerHTML = Foo.CONSTANT1;
<div id="output"></div>
(Technically you could ditch the const CONSTANT1 statement and just return the value from the property definition, but I prefer this because it makes it easier to see all the constants at a glance.)
what you are doing is fine (assuming you realize that your example is just setting the same property twice); it is the equivalent of a static variable in Java (as close as you can get, at least without doing a lot of work). Also, its not entirely global, since its on the constructor function, it is effectively namespaced to your 'class'.
Your constants are just variables, and you won't know if you try and inadvertently overwrite them. Also note that Javascript lacks the notion of "class".
I'd suggest you create functions that return values that you need constant.
To get the taste of Javascript, find Javascript: the Good Parts and learn the idiomatic ways. Javascript is very different from Java.
Also with namespaces
var Constants = {
Const1: function () {
Const1.prototype.CONSTANT1 = 1;
Const1.prototype.CONSTANT2 = 2;
},
Const2: function () {
Const2.prototype.CONSTANT3 = 4;
Const2.prototype.CONSTANT4 = 3;
}
};
You said your coming from Java - why don't you store that class in 1 file then and constants at the end of the file. This is what I use:
filename: PopupWindow.js
function PopupWindow() {
//private class memebers
var popup, lightbox;
//public class memeber or method (it is the same in JS if I am right)
this.myfuncOrmyMemeber = function() {};
}
//static variable
PopupWindow._instance = null;
//same thing again with constant-like name (you can't have "final" in JS if I am right, so it is not immutable constant but its close enough ;) - just remember not to set varibales with BIG_LETTERS :D)
PopupWindow.MY_CONSTANT = 1;
//yea, and same thing with static methods again
PopupWindow._getInstance = function() {};
So only difference is the position of static stuff. It is not nicly aligned inside class curly braces, but who cares, its always ctrl+click in IDE (or I use ctr+l to show all class methods - IntellijIdea can do that in JS dunno how about other IDEs) so your not gonna search it by your eye ;)
Yea and I use _ before static method - it is not needed, I don't know why I started to do that :)
Related
I'm maintaining some legacy code and I've noticed that the following pattern for defining objects is used:
var MyObject = {};
(function (root) {
root.myFunction = function (foo) {
//do something
};
})(MyObject);
Is there any purpose to this? Is it equivalent to just doing the following?
var MyObject = {
myFunction : function (foo) {
//do something
};
};
I'm not about to embark in a holy quest to refactor the whole codebase to my likings, but I'd really like to understand the reason behind that roundabout way of defining objects.
Thanks!
It's called the module pattern http://toddmotto.com/mastering-the-module-pattern/
The main reason is for you to create truly private methods and variables. In your case, it's not meaningful because it's not hiding any implementation details.
Here's an example where it makes sense to use the module pattern.
var MyNameSpace = {};
(function(ns){
// The value variable is hidden from the outside world
var value = 0;
// So is this function
function adder(num) {
return num + 1;
}
ns.getNext = function () {
return value = adder(value);
}
})(MyNameSpace);
var id = MyNameSpace.getNext(); // 1
var otherId = MyNameSpace.getNext(); // 2
var otherId = MyNameSpace.getNext(); // 3
Whereas if you just used a straight object, adder and value would become public
var MyNameSpace = {
value: 0,
adder: function(num) {
return num + 1;
},
getNext: function() {
return this.value = this.adder(this.value);
}
}
And you could break it by doing stuff like
MyNameSpace.getNext(); // 1
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 1 again
delete MyNameSpace.adder;
MyNameSpace.getNext(); // error undefined is not a function
But with the module version
MyNameSpace.getNext(); // 1
// Is not affecting the internal value, it's creating a new property
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 2, yessss
// Is not deleting anything
delete MyNameSpace.adder;
MyNameSpace.getNext(); // no problemo, outputs 3
The purpose is to limit accessibility of functions within the closure to help prevent other scripts from executing code on it. By wrapping it around a closure you are redefining the scope of execution for all code inside the closure and effectively creating a private scope. See this article for more info:
http://lupomontero.com/using-javascript-closures-to-create-private-scopes/
From the article:
One of the best known problems in JavaScript is its dependance on a
global scope, which basically means that any variables you declare
outside of a function live in the same name space: the ominous
window object. Because of the nature of web pages, many scripts from
different sources can (and will) run on the same page sharing a
common global scope and this can be a really really bad thing as it
can lead to name collisions (variables with the same names being
overwritten) and security issues. To minimise the problem we can use
JavaScript’s powerful closures to create private scopes where we can
be sure our variables are invisible to other scripts on the page.
Code:
var MyObject = {};
(function (root) {
function myPrivateFunction() {
return "I can only be called from within the closure";
}
root.myFunction = function (foo) {
//do something
};
myPrivateFunction(); // returns "I can only be called from within the closure"
})(MyObject);
myPrivateFunction(); // throws error - undefined is not a function
advantages:
maintains variables in private scope.
you can extend the functionality of the existing object.
performance is increased.
i think the above three simple points are just enough to follow those rules. And to keep it simple its nothing but writing inner functions.
In the particular case that you show, there is no meaningful difference, in terms of functionality or visibility.
It's likely that the original coder adopted this approach as a sort of template allowing him to define private variables that could be used in the definition of things like myFunction:
var MyObject = {};
(function(root) {
var seconds_per_day = 24 * 60 * 60; // <-- private variable
root.myFunction = function(foo) {
return seconds_per_day;
};
})(MyObject);
This avoids calculating seconds_per_day each time the function is called, while also keeping it from polluting the global scope.
However, there's nothing essentially different from that and just saying
var MyObject = function() {
var seconds_per_day = 24 * 60 * 60;
return {
myFunction: function(foo) {
return seconds_per_day;
}
};
}();
The original coder may have preferred to be able to add functions to the object using the declarative syntax of root.myFunction = function, rather than the object/property syntax of myFunction: function. But that difference is mainly a matter of preference.
However, the structure taken by the original coder has the advantage that properties/methods can be easily added elsewhere in the code:
var MyObject = {};
(function(root) {
var seconds_per_day = 24 * 60 * 60;
root.myFunction = function(foo) {
return seconds_per_day;
};
})(MyObject);
(function(root) {
var another_private_variable = Math.pi;
root.myFunction2 = function(bar) { };
})(MyObject);
Bottom line, there is no need to adopt this approach if you don't need to, but there is also no need to change it, since it works perfectly well and actually has some advantages.
First pattern can be used as a module which takes an object and returns that object with some modifications. In other words, you can define such modules as follows.
var module = function (root) {
root.myFunction = function (foo) {
//do something
};
}
And use it like:
var obj = {};
module(obj);
So an advantage could be the re-usability of this module for later uses.
In the first pattern, you can define a private scope to store your private stuff such as private properties and methods. For example, consider this snippet:
(function (root) {
// A private property
var factor = 3;
root.multiply = function (foo) {
return foo * factor;
};
})(MyObject);
This pattern can be used to add a method or property to all types of objects such as arrays, object literals, functions.
function sum(a, b) {
return a + b;
}
(function (root) {
// A private property
var factor = 3;
root.multiply = function (foo) {
return foo * factor;
};
})(sum);
console.log(sum(1, 2)); // 3
console.log(sum.multiply(4)); // 12
In my opinion the main advantage could be the second one (creating a private scope)
This pattern provides a scope in which you can define helper functions that are not visible in the global scope:
(function (root) {
function doFoo() { ... };
root.myFunction = function (foo) {
//do something
doFoo();
//do something else
};
})(MyObject);
doFoo is local to the anonymous function, it can't be referenced from outside.
Is there something like a best practise when it comes to declaring variables in javascript before assigning a value to them? Sometimes it's necesary for scope reasons, but what if scope doesn't matter?
// Declare first
(function() {
var foo = 'bar',
a = 500,
b = 300,
c;
// Some things get done here with a and b before c can use them...
c = a * b;
// c is now ready to use...
doSomething(c);
}());
// Declare when needed
(function() {
var foo = 'bar',
a = 500,
b = 300;
// Some things get done here with a and b before c can use them...
var c = a * b;
// c is now ready to use...
doSomething(c);
}());
And I'm also wondering what's best practise for something similar with object literals:
// Add property with null assigned to it
var myObj = {
foo: null,
doSomething: function() {
this.foo = 'bar';
}
};
// Property gets added when value is set
var myObj = {
doSomething: function() {
this.foo = 'bar';
}
};
It is mostly a matter of style.
As var declarations are automatically hoisted up to the top of the scope, it makes sense to place them at top of their scope so that you can read the code closer to how the interpreter will execute it.
Declaring variables at the top of their scope is Crockford's recommendation. And it does make sense as it clears up some common misconceptions.
For example:
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 0);
}
Since var has function scope, all iterations (and functions inside of them) refer to the same i. As all three timed functions will execute after the loop ends, the snippet above logs 3 three times.
Now for those with block scoping experience, the above behavior is not very clear. Rewriting the snippet:
var i;
for (i = 0; i < 3; i++) {
// ...
}
Now, i is declared in the global scope, exactly as the previous snippet. However, this one is much more clear on that.
Another misconception:
(function() {
if (true) {
var foo = 1;
} else {
var foo = 1;
}
}());
Again, in block-scoped languages¹ the above is perfectly valid. However, as var declarations are hoisted up to top of the current function scope at parse time, the above is equivalent to:
(function() {
var foo;
var foo;
if (true) {
foo = 1;
} else {
foo = 1;
}
}());
The variable is declared twice. Most browsers will just ignore the second declaration and the code will "work", but static code analysis tools such as JSHint will yell at you.
You can rewrite it with only one declaration and it is perfectly valid:
(function() {
if (true) {
var foo = 1;
} else {
foo = 1;
}
}());
But OCD-like coders like me will find it rather ugly. So again, declaring at top of the scope:
(function() {
var foo;
if (true) {
foo = 1;
} else {
foo = 1;
}
}());
Looks much more tidier.
Again, it is mostly a matter of style. Personally, if I have a giant function, I hate to scroll all the way up just to check whether a variable is already declared and adding it to the list. In that case, I may just add a couple of var declarations in the middle of the function (against Crockford's recommendation) which I personally find easier to read and maintain.
As it is a matter of style, just make sure to keep your code the most maintainable and concise possible.
In the other side of the coin, I'll admit that, personally, I've started and mostly used var declarations when the variable is firstly used. This is an aspect of the language and you can use it this way without problem.
But I will also admit that, if I had followed Crockford's recommendations from the start, I'd have had many less headaches (as with the misconceptions shown above) and would have grasped JavaScript's function scoping aspect much faster.
¹ Note that JS 1.7 introduced block-scoped variables through let, but it is not widely supported yet.
I'm trying to reuse a complicated function, and it would work perfectly if I could change the value of a local variable that's inside a conditional inside that function.
To boil it down:
var func = complicated_function() {
// lots of code
if (something) {
var localvar = 35;
}
// lots of code
}
I need localvar to be some other number.
Is there any way to assign localvar to something else, without actually modify anything in the function itself?
Update: The answer is yes! See my response below.
Is there any way to assign localvar to something else, without actually modify anything in the function itself?
Nope.
No, but it is possible to assign it conditionally so that the function signature (basically, the required input and output) does not change. Add a parameter and have it default to its current value:
var func = complicated_function(myLocalVar) {
// lots of code
if (something) {
// if myLocalVar has not been set, use 35.
// if it has been set, use that value
var localvar = (myLocalVar === undefined)?35:myLocalVar;
}
// lots of code
}
No.
Without changing the complicated function there is no way, in javascript you can manipilate this by using call and apply. You can override functions in the complicated function or add new if this is an option (but they won't be able to access the local variable localvar).
this is more for fun my real answer is still no.
If you are feeling crazy :)
var complicatedFunction = function() {
var i = 10;
var internalStuff = function() {
console.log(i); // 10 or 12?
};
return internalStuff();
};
var complicatedFunction;
eval("complicatedFunction = " + complicatedFunction.toString().replace(/i = 10/, 'i = 12'));
complicatedFunction(); //# => 12
If the function uses this.localvar:
var func = function() {
alert(this.localvar)
if (true) {
var localvar = 35;
}
// lots of code
alert(this.localvar)
}
var obj = {localvar: 10};
func.call(obj); // alerts 10 twice
If not, then you can't change it without changing the function.
In javascript variables are "pushed" to the top of their function. Variables in javascript have function scope, not "curly brace" scope like C, C++, Java, and C#.
This is the same code with you (the developer) manually pushing it to the top:
var func = complicated_function() {
var localvar = 0;
// lots of code
if (something) {
localvar = 35;
}
// lots of code
}
Does declaring the variable "up" one function help you out? At least the declaration is isolated.
function whatever() {
var localvar = 0;
var func = function() {
var something = true;
// lots of code
if (something) {
localvar = 35;
}
// lots of code
};
func();
alert(localvar);
}
whatever();
Here is the jsFiddle: http://jsfiddle.net/Gjjqx/
See Crockford:
http://javascript.crockford.com/code.html
JavaScript does not have block scope, so defining variables in blocks can confuse programmers who are experienced with other C family languages. Define all variables at the top of the function.
I asked this question about three weeks ago and within a half hour got five answers that all basically told me it wasn't possible.
But I'm pleased to announce that the answer is YES, it can be done!
Here's how:
var newfunc = func.toString().replace('35', '42');
eval('newfunc = ' + newfunc);
newfunc();
Of course, it uses eval, which probably means that it's evil, or at least very inadvisable, but in this particular case, it works.
I want to define a single variable used among all instances in the Class definition(which is a plain function constructor in a jQuery plugin).
Is there such a feature?
If there is,just a simple demo and I think I'll understand.
What you're looking for is essentially a private static or protected static variable, which can't be 100% emulated in javascript (that I know of).
You can make public static or private, though.
tehMick's solution gives you public static with some convenience setters/getters, but it's really no different than if you replaced y.setB(2) with A.b = 2.
Here's how a private variable would work, but understand that this is still a per instance variable, and reflects the same value via the getter only because each instance sets it to the same literal string.
function SomeClass()
{
var privateVariable = 'foo';
this.publicVariable = 'bar';
this.getPrivateVariable = function()
{
return privateVariable;
}
this.setPrivateVariable = function( value )
{
privateVariable = value;
}
}
SomeClass.staticVariable = 'baz';
var a = new SomeClass();
var b = new SomeClass();
// Works...
alert( a.getPrivateVariable() );
alert( b.getPrivateVariable() );
// Until we try to set it...
a.setPrivateVariable( 'hello' );
// Then it breaks
alert( a.getPrivateVariable() );
alert( b.getPrivateVariable() );
Javascript doen't really provide that kind of data hiding, but this may suit your purposes:
function A()
{
if (!A.b) A.b = 1;//shared
//this.b = 0;//not shared
}
A.prototype.getB = function()
{
return A.b;//shared
//return this.b;//not shared
}
A.prototype.setB = function(value)
{
A.b = value;//shared
//this.b = value//not shared
}
function load()
{
var x = new A();
var y = new A();
y.setB(2);
document.body.innerHTML += x.getB();
}
output: 2
Your question is not very clear. Do you mean a global variable? A variable that can be accessed from any object?
EDIT (based on comments)
You can do something like this to make the variables scoped to just your code:
//This function will execute right away (it is basically the same as leaving it out,
//except that anything inside of it is scoped to it.
(function(){
var globalToThisScope = "this is global ONLY from within this code section";
window.object = {
//Now any instance of this object can see that variable,
// but anything outside of the outer empty function will not see anything
};
})();
I concur with Peter Bailey (+1). Douglas Crockford has a discussion of public and private instance variables; Peter suggests a nice way to add static public variables.
In javascript, can I declare properties of an object to be constant?
Here is an example object:
var XU = {
Cc: Components.classes
};
or
function aXU()
{
this.Cc = Components.classes;
}
var XU = new aXU();
just putting "const" in front of it, doesn't work.
I know, that i could declare a function with the same name (which would be also kind of constant), but I am looking for a simpler and more readable way.
Browser-compatibility is not important. It just has to work on the Mozilla platform, as it is for a Xulrunner project.
Thank you a lot!
Cheers.
Since you only need it to work on the Mozilla platform, you can define a getter with no corresponding setter. The best way to do it is different for each of your examples.
In an object literal, there is a special syntax for it:
var XU = {
get Cc() { return Components.classes; }
};
In your second exampe, you can use the __defineGetter__ method to add it to either aXU.prototype or to this inside the constructor. Which way is better depends on whether the value is different for each instance of the object.
Edit: To help with the readability problem, you could write a function like defineConstant to hide the uglyness.
function defineConstant(obj, name, value) {
obj.__defineGetter__(name, function() { return value; });
}
Also, if you want to throw an error if you try to assign to it, you can define a setter that just throws an Error object:
function defineConstant(obj, name, value) {
obj.__defineGetter__(name, function() { return value; });
obj.__defineSetter__(name, function() {
throw new Error(name + " is a constant");
});
}
If all the instances have the same value:
function aXU() {
}
defineConstant(aXU.prototype, "Cc", Components.classes);
or, if the value depends on the object:
function aXU() {
// Cc_value could be different for each instance
var Cc_value = return Components.classes;
defineConstant(this, "Cc", Cc_value);
}
For more details, you can read the Mozilla Developer Center documentation.
UPDATE: This works!
const FIXED_VALUE = 37;
FIXED_VALUE = 43;
alert(FIXED_VALUE);//alerts "37"
Technically I think the answer is no (Until const makes it into the wild). You can provide wrappers and such, but when it all boils down to it, you can redefine/reset the variable value at any time.
The closest I think you'll get is defining a "constant" on a "class".
// Create the class
function TheClass(){
}
// Create the class constant
TheClass.THE_CONSTANT = 42;
// Create a function for TheClass to alert the constant
TheClass.prototype.alertConstant = function(){
// You can’t access it using this.THE_CONSTANT;
alert(TheClass.THE_CONSTANT);
}
// Alert the class constant from outside
alert(TheClass.THE_CONSTANT);
// Alert the class constant from inside
var theObject = new TheClass();
theObject.alertConstant();
However, the "class" TheClass itself can be redefined later on
If you are using Javascript 1.5 (in XUL for example), you can use the const keyword instead of var to declare a constant.
The problem is that it cannot be a property of an object. You can try to limit its scope by namespacing it inside a function.
(function(){
const XUL_CC = Components.classes;
// Use the constant here
})()
To define a constant property, you could set the writable attribute to false in the defineProperty method as shown below:
Code snippet:
var XU = {};
Object.defineProperty(XU, 'Cc', {
value: 5,
writable: false
});
XU.Cc = 345;
console.log(XU.Cc);
Result:
5 # The value hasn't changed