Constant Variables in Javascript - javascript

I am trying to have some const global variables which I can use in the javascript and I came out with this code and picking up from some answers referred in SO. But it seems that I have a little mistake somewhere which I couldn't spot. Can someone help me with this?
in testQuery.js
(function (window, undefined) {
var testQuery = function(obj) {
if (!(this instanceof testQuery)) {
return new testQuery(obj);
}
}
var MYGLOBALS = function() {
var globals = {
foo : "bar",
batz : "blah"
}
return {
getValue : function(s) {
return globals[s];
}
}
}();
window.testQuery = testQuery;
}) (window);
and in the html javascript tag i have this line of code.
in testQuery.html file
<html>
<head>
<script src="testQuery.js"></script>
<script>
function onClick() {
alert(MYGLOBALS.getValue("foo"));
}
</script>
</head>
<body>
<input type="button" onclick="onClick()">
</body>
</html>

The variable MYGLOBALS is local to your scoping function (the big outermost function that has no name), so it can only be accessed from within that function.
I'm not sure what you mean by "...in the html javascript tag..." but if the alert you've quoted is outside that scoping function, MYGLOBALS is out of scope for it.
Update: The thing about JavaScript scope is that it's much simpler than people think it is. Variables declared with var are private to the scope (function or global; JavaScript has no block-level scope so just {} doesn't do it) in which they're declared, and sub-scopes of that scope (e.g., functions declared or define within it). And scope is entirely lexical — that is, it is what you see in the source code, not dictated by some other runtime structure. They don't pop out of that scope unless you see code somewhere explicitly making that happen, as with your window.testQuery = testQuery; line, which explicitly makes testQuery a property on window and therefore a global variable. (And even then, it's not that the variable has popped out of the scope, just that you've created a new property referring to the same thing which is more broadly-accessible.)
Update 2: Re your comment
Actually what I am trying to do is to create something like what you would see when you are doing programming in other language where there will be a final static integer which you can put into the parameters fields on the functions you call. is there a better way of doing it? For example, in visual basic its something like me.background = Color.YELLOW. what I want is to have a static variable which will represent that YELLOW color.
JavaScript doesn't have user-defined constants, and doesn't have enums. (Update: Both of those things may change with ES6.) What you do instead is define an object with the properties, e.g.:
var COLORS = {
RED: "#FF0000",
BLUE: "#0000FF",
// ...
GREEN: "#00FF00"
};
Those aren't constants, there's nothing to keep anyone from assigning to COLORS.RED except your telling them not to.
(Update: In ES5, we can make those properties constant using Object.defineProperties, like this:
var COLORS = Object.defineProperties({}, {
RED: {value: "#FF0000"},
BLUE: {value: "#0000FF"},
// ...
GREEN: {value: "#00FF00"}
});
When you define a property that way, by default it's not writable.)
For what you're doing, you probably want the module pattern, where you have a single global symbol whose value is an object, and everything else is properties on that object:
(function() {
var mod;
// Create the global, and also give ourselves a convenient alias for it (`mod`)
window.MyModule = mod = {};
// Colors
mod.COLORS = {
RED: "#FF0000",
BLUE: "#0000FF",
// ...
GREEN: "#00FF00"
};
mod.testQuery = MyModule_testQuery;
function MyModule_testQuery() {
// Do something
}
})();
alert(MyModule.COLORS.RED); // #FF0000
MyModule.testQuery(); // Do something
Or if you prefer, that testQuery function could be defined like this:
mod.testQuery = function() {
// Do something
};
...but then the function is anonymous, and I'm not a fan of anonymous functions. (Note that there's nothing special about the name MyModule_testQuery, that's purely my naming convention.)
Somewhat off topic:
Regarding this line where we're publishing our global symbol above:
// Create the global, and also give ourselves a convenient alias for it (`mod`)
window.MyModule = mod = {};
Note that that is very specific to browser environments. We could make it applicable to any JavaScript environment with a trivial change:
// Create the global, and also give ourselves a convenient alias for it (`mod`)
this.MyModule = mod = {};
That works because we're the ones who call the outermost scoping function, and so we know that we're not calling it with any particular this value (this in JavaScript — unlike some other languages — is determined entirely by how a function is called, not where or how it's defined). So since we know we're not using any special this value, we know that it will be the global object, because that's how JavaScript works. And the global object is window on web browsers (effectively; technically window is a property on the global object that refers back to itself).

http://jsfiddle.net/vXu7m/1/
Some syntactic cleanup, and attaching you MYGLOBALS to the window object should do what you want.

Related

Javascript constructor and arguments

It is my first question here, so apologise if I missed anything.
Perhaps solution for my problem could be find, but I have no idea how to search for it, no clues about how to ask it in google or something.
I have a following problem, let's have such constructor
const Product = function (color) {
let self = {};
self.setColor = function(colorToSet) {
color = colorToSet;
}
self.getColor = function() {
return color;
}
return self;
};
now when I tried to use:
let self = {}, color;
in chrome console I received error that color has been already declared, so I removed color field and after this (with a snippet code above), magic happened that I cannot explain.
let's say I will write something like this:
let a = Product("Yello");
a.getColor() ----> "Yellow"
a.setColor("red");
a.getColor() ----> "red";
If it returns color for the first time, then it has to be declared somehow.
I do not know where is color field, I cannot find it in the object nor in its prototype, nowhere actually. Could you explain me why ? and where it is ?
I know that I can just declare color for example:
self.color = color;
But I want to know how is working the example above and what happened with color field.
Also could you tell me if I can use let with declaring values from parameters in such way ?
const Product = function (color) {
let self = {}, color;
self.setColor = function(colorToSet) {
color = colorToSet;
}
self.getColor = function() {
return color;
}
return self;
};
It's not magic :) this behaviour happens because:
You're returning an object that has two methods which are
closures.
When a function is defined within another function and then a reference to it stored somewhere (in this case when you returned then attached to the self variable) then a closure is created.
In short, a function has access to variables created inside its definition block and to its enclosing environment (your constructor definition).
As a result it will have access to any variables in the enclosing scope at the time the parent was invoked.
This includes any parameters of that enclosing Product function, i.e. the color argument you define.
So:
You invoke Product passing in a colour and store this in a variable a. At this point a will contain a reference to an object whose properties include two methods getColor and setColor
since the latter methods are closures, they have access to their enclosing scope at the time Product (their enclosing function environment was called). Since Product was invoked with a color, a variable called color local to Product but also available to any closures will be created and assigned the value passed in. In this case color will be equal to 'Yellow
Since both methods were defined in the same scope at the same time, they both have access to this variable, producing the results you experienced.
It has to be declared somehow. I do not know where is color field, I cannot find it in the object nor in its prototype, nowhere actually. Could you explain me why? and where it is?
It is the variable that you declared by using it as a parameter name. That parameter variable is scoped to the Product function, i.e. can be used anywhere inside it. It's the reason why you get an "already declared" error if you try to use let color.
Your methods can access (read/write) this local variable because they are closures.

Overwrite a function in a function

I am trying to figure out how to extend :
var outdatedBrowser = function(options) {
function startStylesAndEvents() {
console.log("bleh");
}
}
I am trying to overwrite the function startStylesAndEvents without touching the source code of the library : https://github.com/burocratik/outdated-browser/blob/develop/outdatedbrowser/outdatedbrowser.js
So when I call:
outdatedBrowser({
bgColor: '#f25648',
color: '#ffffff',
lowerThan: 'transform',
languagePath: 'your_path/outdatedbrowser/lang/en.html'
})
and it uses the startStylesAndEvents function, it uses mine instead of theirs...
Thanks!
Without modifying the original source? You can't.
All of JavaScript scoping is based on functions (ignoring let, const and class for the moment). If a value is declared inside of a function, it cannot be accessed outside of that function unless it is returned from the function or modifies some external value.
For example, imagine a function like this:
function doStuff() {
var times = 10;
for (var i = 0; i < times; i++) {
doThing(i);
}
}
Your question is semantically identical to asking how to change times. It just can't be done.
The inner function is contained within a closure, which you don't have access to. Unfortunately (contrary to the "nothing is impossible" ideology) this can't be done at runtime.
That is what you might call a 'private' function. The function is stored just like any other variable. In JavaScript that generally means it has to be 'local scope' (instead of a member variable) so it cannot be overridden. (if only they had used this.functionName... then you could override more easily)
The good news is, there is a hack which seems to be cross-browser compatible. (tested in IE 11, with emulation options back to IE 5!) In JavaScript, you can replace the actual 'source code' of the function itself. (a bit different than a proper override)
var newInnerFunction = function () { // intentionally anonymous for use in eval
}
var overriddenFunction = eval(
outdatedBrowser.toString() // expecting outdatedBrowser to be anonymous for use in eval
.replace('{', '{var startStylesAndEvents=' + newInnerFunction.toString() + ';')
)
Note that outdatedBrowser is an anonymous function (simply function()). If it were named, then the use of eval would have the side effect of adding the new function to the namespace under its original name. An additional replace could take care of that if it were an issue.
Most probably, you can't. But it's not completely impossible.
For example, if you call startStylesAndEvents inside a with statement whose scope object has been leaked to the outside
var scope = Object.create(null);
var outdatedBrowser = function(options) {
function startStylesAndEvents() {
console.log("bleh");
}
with(scope) {
startStylesAndEvents(); // You expect this to be the private function above
}
}
outdatedBrowser(); // "bleh"
Then, you can hijack calls to startStylesAndEvents:
scope.startStylesAndEvents = function() {
console.log("blah");
};
outdatedBrowser(); // "blah"
Don't do this, of course. It's evil, slow and not allowed in strict mode.

Declare javascript function with extra properties in a single statement?

I know I can define properties on functions, which can then be accessed from within the function. Right now, the only syntax I can work out involves two statements. Is there a more concise way to express the following:
function myFunc() {
// do some work
}
myFunc.myProp = 0;
I'm not looking for a solution that is fewer characters -- this isn't code golf. I'm asking something more along the lines of "are there different patterns of function declaration that have this other desirable merit?" This is almost about ways to use closures (because I suspect the answer lies there).
Thanks!
Especially if you want to access properties of the function from inside the function itself, you're better off doing this:
var theFunction = function() {
function theRealFunction() {
// the code
if (theRealFunction.something == "not whatever")
// do something
// more code
}
theRealFunction.something = "whatever";
return theRealFunction;
}();
What that does is wrap your function declaration up in an anonymous function. The problem with accessing function properties via the function name is that it must do that by finding the function's name in the surrounding scope. That's kind-of icky, but at least this way it involves a scope that's essentially private. It'll work whether or not the resulting function (returned as the return value of the anonymous function) is assigned to a different variable, passed to a function as a handler function, etc.
This really, really all depends. If you're looking for private variables, then you can easily return a function from the function -- an inner-function will contain access to its parent's scope.
var outer_function = (function () {
var private_var = "secret",
public_var = "public",
inner_function = function () {
return private_var;
};
inner_function.public_var = public_var;
return inner_function;
}());
outer_function now equals inner_function, with the benefit of having access to the enclosed data. Any properties attached to the inner (in the way you did) will now be accessible as public properties of outer.
To this end, you can return, say, a constructor for a class, with public-static properties, with the enclosed vars acting as private-static properties, shared between every instance of the "class" you build.
Not exactly the answer to your question, but if you ever want to read up some different design patterns that can be used when defining a javascript function, this is one of the best articles I've ever read on the topic:
http://www.klauskomenda.com/code/javascript-programming-patterns/

what is self-executing anonymous function or what is this code doing?

var module = {};
(function(exports){
exports.notGlobalFunction = function() {
console.log('I am not global');
};
}(module));
function notGlobalFunction() {
console.log('I am global');
}
notGlobalFunction(); //outputs "I am global"
module.notGlobalFunction(); //outputs "I am not global"
Can anyone help me understand what's going on here? I get that if you call notGlobalFunction(), it will just call the second function.
But what is var module = {} doing? and why is it called again inside the first function?
It says this is commonly known as a self-executing anonymous function but I don't really know what that means.
Immediately invoked functions are typically used to create a local function scope that is private and cannot be accessed from the outside world and can define it's own local symbols without affecting the outside world. It's often a good practice, but in this particular case, I don't see that it creates any benefit other than a few more lines of code because it isn't used for anything.
This piece of code:
(function(exports){
exports.notGlobalFunction = function() {
console.log('I am not global');
};
}(module));
Would be identical to a piece of code without the immediate invocation like this:
module.notGlobalFunction = function() {
console.log('I am not global');
};
The one thing that is different is that in the first, an alias for modules called exports is created which is local to the immediately invoked function block. But, then nothing unique is done with the alias and the code could just as well have used modules directly.
The variable modules is created to be a single global parent object that can then hold many other global variables as properties. This is often called a "namespace". This is generally a good design pattern because it minimizes the number of top-level global variables that might conflict with other pieces of code used in the same project/page.
So rather than make multiple top level variables like this:
var x, y, z;
One could make a single top level variable like this:
var modules = {};
And, then attach all the other globals to it as properties:
modules.x = 5;
modules.y = 10;
modules.z = 0;
This way, while there are still multiple global variables, there is only one top-level global that might conflict with other pieces of code.
Similarly, an immediately invoked function creates a local, private scope where variables can be created that are local to that scope and cannot interfere with other pieces of code:
(function() {
var x, y, z;
// variables x, y and z are available to any code inside this immediately invoked function
// and they act like global variables inside this function block and
// there values will persist for the lifetime of the program
// But, they are not truly global and will not interfere with any other global
// variables and cannot be accessed by code outside this block.
// They create both privacy and isolation, yet work just as well
})();
Passing an argument into the immediately invoked function is just a way to pass a value into the immediately invoked function's scope that will have it's own local symbol:
(function(exports) {
// creates a local symbol in this function block called exports
// that is assigned an initial value of module
})(module);
This creates a new empty object:
var module = {};
It does the same as:
var module = new Object();
This wrapper:
(function(exports){
...
}(module));
only accomplishes to add an alias for the variable module inside the function. As there is no local variables or functions inside that anonymous function, you could do the same without it:
module.notGlobalFunction = function() {
console.log('I am not global');
};
An anonymous function like that could for example be used to create a private variable:
(function(exports){
var s = 'I am not global';
exports.notGlobalFunction = function() {
console.log(s);
};
}(module));
Now the method notGlobalFunction added to the module object can access the variable s, but no other code can reach it.
The IIFE is adding a method to the module object that is being passed in as a parameter. The code is demonstrating that functions create scope. Methods with the same name are being added to a object and the the head object (window) of the browser.
"self-executing" might be misleading. It is an anonymous function expression, that is not assigned or or given as an argument to something, but that called. Read here on Immediately-Invoked Function Expression (IIFE).
what is var module = {} doing?
It initializes an empty object that is acting as a namespace.
why is it called again inside the fist function?
It is not "called", and not "inside" the first function. The object is given as an argument ("exports") to the IEFE, and inside there is a property assigned to it.

Accessing variables from other functions without using global variables

I've heard from a variety of places that global variables are inherently nasty and evil, but when doing some non-object oriented Javascript, I can't see how to avoid them. Say I have a function which generates a number using a complex algorithm using random numbers and stuff, but I need to keep using that particular number in some other function which is a callback or something and so can't be part of the same function.
If the originally generated number is a local variable, it won't be accessible from, there. If the functions were object methods, I could make the number a property but they're not and it seems somewhat overcomplicated to change the whole program structure to do this. Is a global variable really so bad?
I think your best bet here may be to define a single global-scoped variable, and dumping your variables there:
var MyApp = {}; // Globally scoped object
function foo(){
MyApp.color = 'green';
}
function bar(){
alert(MyApp.color); // Alerts 'green'
}
No one should yell at you for doing something like the above.
To make a variable calculated in function A visible in function B, you have three choices:
make it a global,
make it an object property, or
pass it as a parameter when calling B from A.
If your program is fairly small then globals are not so bad. Otherwise I would consider using the third method:
function A()
{
var rand_num = calculate_random_number();
B(rand_num);
}
function B(r)
{
use_rand_num(r);
}
Consider using namespaces:
(function() {
var local_var = 'foo';
global_var = 'bar'; // this.global_var and window.global_var also work
function local_function() {}
global_function = function() {};
})();
Both local_function and global_function have access to all local and global variables.
Edit: Another common pattern:
var ns = (function() {
// local stuff
function foo() {}
function bar() {}
function baz() {} // this one stays invisible
// stuff visible in namespace object
return {
foo : foo,
bar : bar
};
})();
The returned properties can now be accessed via the namespace object, e.g. ns.foo, while still retaining access to local definitions.
What you're looking for is technically known as currying.
function getMyCallback(randomValue)
{
return function(otherParam)
{
return randomValue * otherParam //or whatever it is you are doing.
}
}
var myCallback = getMyCallBack(getRand())
alert(myCallBack(1));
alert(myCallBack(2));
The above isn't exactly a curried function but it achieves the result of maintaining an existing value without adding variables to the global namespace or requiring some other object repository for it.
I found this to be extremely helpful in relation to the original question:
Return the value you wish to use in functionOne, then call functionOne within functionTwo, then place the result into a fresh var and reference this new var within functionTwo. This should enable you to use the var declared in functionOne, within functionTwo.
function functionOne() {
var variableThree = 3;
return variableThree;
}
function functionTwo() {
var variableOne = 1;
var var3 = functionOne();
var result = var3 - variableOne;
console.log(variableOne);
console.log(var3);
console.log('functional result: ' + result);
}
functionTwo();
If another function needs to use a variable you pass it to the function as an argument.
Also global variables are not inherently nasty and evil. As long as they are used properly there is no problem with them.
If there's a chance that you will reuse this code, then I would probably make the effort to go with an object-oriented perspective. Using the global namespace can be dangerous -- you run the risk of hard to find bugs due to variable names that get reused. Typically I start by using an object-oriented approach for anything more than a simple callback so that I don't have to do the re-write thing. Any time that you have a group of related functions in javascript, I think, it's a candidate for an object-oriented approach.
Another approach is one that I picked up from a Douglas Crockford forum post(http://bytes.com/topic/javascript/answers/512361-array-objects). Here it is...
Douglas Crockford wrote:
Jul 15 '06
"If you want to retrieve objects by id, then you should use an object, not an
array. Since functions are also objects, you could store the members in the
function itself."
function objFacility(id, name, adr, city, state, zip) {
return objFacility[id] = {
id: id,
name: name,
adr: adr,
city: city,
state: state,
zip: zip
}
}
objFacility('wlevine', 'Levine', '23 Skid Row', 'Springfield', 'Il', 10010);
"The object can be obtained with"
objFacility.wlevine
The objects properties are now accessable from within any other function.
I don't know specifics of your issue, but if the function needs the value then it can be a parameter passed through the call.
Globals are considered bad because globals state and multiple modifiers can create hard to follow code and strange errors. To many actors fiddling with something can create chaos.
You can completely control the execution of javascript functions (and pass variables between them) using custom jQuery events....I was told that this wasn't possible all over these forums, but I got something working that does exactly that (even using an ajax call).
Here's the answer (IMPORTANT: it's not the checked answer but rather the answer by me "Emile"):
How to get a variable returned across multiple functions - Javascript/jQuery

Categories