Here i am just creating a global namespace for my application and everything works as expected
var MYAPP = MYAPP || {} ;
but if I omit var keyword ( i know it's not the right way), javascript throw an error "ReferenceError: MYAPP2 is not defined" .
MYAPP2 = MYAPP2 || {};
just out of curiosity can some one explain me in second case why javascript is not able to resolve the reference.
The first version doesn't produce an error because Javascript's variable hoisting makes it equivalent to this:
var MYAPP; // declares, but leaves the value undefined / unchanged
MYAPP = MYAPP || {}; // creates, if the value was previously undefined
Importantly, the declaration part of this does not overwrite any existing declaration or assignment that was already made to the variable.
This is what allows this pattern to be used repeatedly within a single scope. MYAPP either retains the value it already had, or is initialised to an empty object.
in the second case, that declaration step is effectively omitted. If the variable has not already been declared (or otherwise exists in scope, i.e. as a property of the global object) then the error you see is generated.
var MYAPP = MYAPP || {} declares variable MYAPP in current scope (aka execution context). If declaration appears in a function - local variable is declared; if it's in global scope - global variable is declared.
MYAPP2 = MYAPP2 || {}, on the other hand, is merely a property assignment. It first tries to resolve MYAPP2 against scope chain. If it finds it anywhere in that scope chain, it performs assignment; if it doesn't find MYAPP2, only then it creates x property on a global object (which is a top level object in a scope chain).
var keyword declare immediately variable you are referencing to
var a = a || {};
is like as
var a; a = a || {};
In second case you are refencing to variable isn't declared yet.
Related
The function below will return b is not defined because the compiler will look in the function and then into the global scope in search for a variable b.
However, I assumed that defining b without the word var would automatically create a global variable?
Can anyone explain the rules when omitting the word var?
function foo(a) {
console.log( a + b );
b = a;
}
foo( 2 );
Not using var in a function for a variable declaration does make it global, but in your case, the JavaScript engine is hitting this line:
console.log( a + b );
before it hits this line:
b = a;
And, that's the line that declares it (globally).
And, because you didn't use var, the declaration is not hoisted to the top of the code base (which it would have been with var - you would still not have gotten a value for b because only the declaration would be hoisted, not the initialization, but it would not have thrown an error), so you get your error.
See more about var and hoisting here.
In strict mode:
Using an undeclared variable will throw an exception
In non-strict mode:
Assigning to an undeclared variable will create a global, but this is not hoisted
Declaring a variable with var creates a local variable and is hoisted to the top of the function
Reading an undeclared variable will throw an exception
Since you are not in strict mode and you try to read b before you assign a value to it, you get an exception.
Guidelines to follow:
Always "use strict"
Always declare your variables
Declare them in the global scope if you want them there
… but try to avoid global scope. Consider using a closure instead if you think a global would be useful.
Variables declared this way b = a are not hoisted, like variables declared with the var keyword. That means that, at runtime, the compiler reads b, not as undefined (as would happen with var b = a), but as something that doesn´t exist at all, thus throwing a ReferenceError.
Info on Hoisting: https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
Take the following block of code. There is no return statement, and yet MyApp.VideoTracker is a property on the window object and so is accessible globally.
(function(window, $, VideoTracker, undefined) {
"use strict";
VideoTracker.loadAPI = function(apiReadyCallbackFn) {
};
VideoTracker.destroy = function(iframeElement) {
};
VideoTracker.trackVideos = function() {
};
$().ready(function() {
var youTubeIframes = $('iframe[src*="youtube.com"]');
if (youTubeIframes.length > 0) {
VideoTracker.loadAPI(VideoTracker.trackVideos);
}
});
}(window, jQuery, MyApp.VideoTracker = MyApp.VideoTracker || {}));
Is this because of the way it is defined in the function call, i.e.:
MyApp.VideoTracker = MyApp.VideoTracker || {}
An explanation would be great, as I can see this must be the reason but don't understand why?
Yes, essentially you're calling the IIFE with what are global variables.
Assuming you've defined MyApp already - and before the function body is executed - you're calling it with an expression that either sets the VideoTracker property of MyApp with the existing MyApp.VideoTracker or an empty object literal, and that reference is being passed into your IIFE.
Hope that helps.
That's because your MyApp is a Global object already- it doesn't become one, because of your self invoked function.
How else do you think you would be able to access its VideoTracker property or define it if it's not there?
In a case in which MyApp object doesn't exist as a part of a higher context in which your IIFE is being executed, it should rise a Reference Error! because MyApp object is neither defined, nor being created within your given IIFE context.
I'm studying variable scope in Javascript, and have come across the difference between variable declaration, and variable initialization. From talking to a developer I know, my understanding is that writing var before a variable declaration assigns the variable to the local scope, while not writing var before declaring the variable assigns the variable to the global scope. Is this true?
If writing var before declaring a variable does assign the variable to the local scope, is it necessary to write var later, when initializing the variable to keep it in the local scope? For example:
var someVariable;
// Do some things with JavaScript
someVariable = 'Some Value'
Since I declared someVariable in the local scope with var, but then initialized someVariable without using var, does JavaScript think that I just initialized one variable in the local scope, or that I declared one variable in the local scope, and then declared and initialized another variable in the global scope?
Later on, when I want to change the value of someVariable again, do I need to write var before the variable expression, or will JavaScript know that I'm changing the value of an already declared local variable? Technically speaking, how does JavaScript know when I'm changing the value of an already declared local variable, and when I'm declaring and initializing a global variable?
var something = "Initial value."
This means: "create a variable in the local scope and give it an initial value". The local scope means the function in which you use this statement.
something = "New value."
This means: "find variable 'something' in the nearest scope, and assign it a new value".
If you use the second statement without ever using the first, the statement will look for any definition of something in progressively bigger scopes (the function that contains your function, if it exists, the function that contains that, etc., until it reaches the global scope). If it finds something, it will assign to an already existing variable. If it finds nothing, it will create a global variable with that name.
If you use var first, you simply ensure that this search always stops at local scope.
These are the same:
var x;
// ...
x = 1;
...and...
var x = 1;
Both define a variable in the local scope and assign a value to it. If you want to change the value of the variable later in the same scope you can simply reference it by name:
x = 2;
If you're in a different scope however, unless the variable was declared in the global scope in the first place you will not be able to access it (it's "out of scope"). Attempting to do so will define a variable with that name in the global scope.
function a(){
var x = 1;
}
function b(){
x = 2; // 'x' in a is out of scope, doing this declares a new 'x' in global scope
}
a();
b();
When referencing a variable in the same scope it was declared, you do not need to prefix it with var, though you can:
var x = 1;
// ...
var x = 2;
...there's no need to do that. While it assigns 2 to 'x', it logically has no effect since var is already in local scope. If x had been declared globally however:
var x = 1;
function a(){
var x = 2;
console.log(x);
}
a();
console.log(x);
This will print first '2' and then '1'. By referencing x preceded with var in the function, it applies the local scope to the variable. Once the function completes the variable's original scope is restored (or the re-scope is lost, if you want to look at it that way). Thanks to #zzzzBov for pointing this out.
Hope this helps.
my understanding is that writing var before a variable declaration assigns the variable to the local scope, while not writing var before declaring the variable assigns the variable to the global scope. Is this true?
Not entirely.
function foo() {
var a = 1;
function bar() {
a = 2; // Still in the scope of foo, not a global
}
}
Since I declared someVariable in the local scope with var, but then initialized someVariable without using var, does JavaScript think that I just initialized one variable in the local scope, or that I declared one variable in the local scope, and then declared and initialized another variable in the global scope?
There is only one someVariable in that example.
Later on, when I want to change the value of someVariable again, do I need to write var before the variable expression
var scopes a variable for the entire function, no matter where in the function it appears.
If you define a variable using var, you can refer to the same variable without using the var keyword over and over. These refer to the same variable:
var someVariable;
//...code...
someVariable = 'rawr';
If you did use the var keyword every time you were changing the variable, you wouldn't get separate variables. The newest declaration would just overwrite the oldest declaration. So there's no point in using the var keyword except for initialization. To change the value of someVariable, you can just make assignments to the variable name like in the above example.
Basically, using var will create a new variable if there is no variable in that scope with the same name.
Now take this code for example:
var someVariable = 'initialized';
function test1(){
//this someVariable will be a new variable since we have the var keyword and its in a different scope
var someVariable = 'test1';
console.log(someVariable);
}
function test2(){
//because there is no var keyword this refers to the someVariable in the parent scope
someVariable = 'test2';
console.log(someVariable);
}
console.log(someVariable); //initialized
test1(); //test1
console.log(someVariable); //initialized
test2(); //test2
console.log(someVariable); //test2
With this example you can see that depending on what you want the code to do, you could be having problems. If you wanted test2 to act like test1 and forgot to use the var keyword you would be confused when you were expecting someVariable to be initialized and instead it was test2.
But you could have also purposely not used the var keyword because you wanted test2 to update the parent variable. So it is important that you use the var keyword correctly.
Not using var when initializing variables will create the variable on the global scope. This is not good practice. If you want variables on the global scope, manually put them there. i.e. window.someVariable = 'initialize'; That way anyone else that sees your code knows that you made it a global variable on purpose.
let's suppose we have a javascript function and we want to check if the second parameter is undefined, in that case we want to assign it a value such as
function myFunc(a,b){
if(typeof b==="undefined" ){
b=0;
}
//do stuff
}
Does the variable b in the if block still refer to the function's parameter or a global variable named b is created?
Cheers
Yes, b gets resolved in the lexicalEnvironment (ES5) respectively Activation Object (ES3). It will always get resolved locally, even if a global variable b exists aswell by accessing the pure name.
You would need to explicitly call window.b respectively global.b (node) to access that global variable with the same name.
It refers to the function's parameter. You can test yourself like so:
var b = 45;
function myFunc(a,b){
if(typeof b==="undefined" ){
b=0;
}
alert( b ); //It will output 0
//do stuff
}
myFunc('');
The answers by #Andre and #Nelson are both correct, but just for clarity's sake:
var c = 123;
var func = (function(a)//a === 1234
{
var b = c;//local b === global c
return function(a,c)
{
console.log(c === b);//false, unless second argument was 123
console.log(a === 1234);//false, unless first arg was 1234
console.log('a masks the a of the outer scope');
};
})(1234);
JS will first scan the scope of the called function, for any vars used, if it doesn't find them there, it moves on to the outer scope. This can be another function, or, eventually, the global scope. In this example, the inner (returned) function will not be able to access the value of a as defined in the outer function. It's GC'ed when that outer function returned, because it's not being referenced anywhere.
code:
function myFunc(a,b){
if(typeof b==="undefined" ){
b=0;
}
console.log('b from myFunc:'+b)
}
myFunc(5);
console.log('global:'+b)
output:
b from myFunc:0
b is not defined
Javascript first looks in the local scope for either a local variable or a named function argument. If it finds the symbol there, then that variable is the one that is used.
Only if a matching local symbol is not found is a global symbol used.
Thus, in your example, you will be setting the value of b the function argument.
Once you've defined a local symbol in either a local variable or a named function argument, you can no longer use that name by itself to access a global variable of the same name. If you specifically want to address the global variable, you can do so by prefixing it with window. as in window.b. This specifically targets the global scope so the local scope is not used.
The variable stays on the function if;
the variable is declared inside the function using var or without it
the variable is declared with this as it's parent node the function, example below
function foo(){
this.bar = 'hello';
}
the variable becomes available in the global scope when
the variable is declared outside any function using var or without it
the variable is declared as it's parent node is window example below
window.bar ='i am global'
YOU NEED DEFINE VARIABLE GLOBALLY :
In the below code t2 is undefined.
<script>
var t1="";
var t2;
function check(t1,t2){
if (t1===undefined)
{
alert("t1 is undefined");
}
if (t2===undefined)
{
alert("t2 is undefined");
}
}
</script>
REF :
http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_undefined
I get a strange behavior when declaring an object with the logical OR.
my_var = my_var || {}; // throws TypeError
If I add the var keyword
var my_var = my_var || {}; // returns empty object
Why is this? I can't seem to find an explanation. my_var is global scope, so why is var changing the behavior?
The first example tries to assign to a property on the global object named my_var by reading the value from an identifier called my_var (OR an empty object). However, the identifier my_var is not defined at that point, so it fails.
In the second example, due to how javascript variable hoisting works, the my_var variable is already declared, when you read from it by assign to it.
Also have a look at this example:
a = a; // fails, undeclared identifier
a = 0;
With var keyword it will work!
b = b; // succeeds allthough identifier undeclared?!
var b = 0;
This is because variable hoisting will turn it into this:
var b; // declaration of b hoisted to the top of scope
b = b;
b = 0;
when defining a variable without var, you're directly accessing the global object. That means, your Javascript engine trys to lookup my_var on the global object (window if you're in a browser). Since that property does not exist yet, your JS engine will throw.
That happens on the right side of your statement, when your engine trys to read a variable with the name my_var. assigning like
my_var = {};
would work tho. But accessing an identifier without var will cause the browser to lookup the scopechain. Since the variable object for the global object is the global object itself, the lookup procedure will end up nowhere ( = exception ).
By putting the var keyword infront, your js engine knows at parsetime that it has to declare a new variable with that identifier name. It actually does declare that variable with an undefined value (that is called "hoisting"). That means, using var will prematurely create a property in the current context with that name. So if that code is not located in any function or eval context, it'll create the property my_var on the window object.
In your second example, the var defines the scope of my_var. This allows the value to be set properly. Here's a quick and dirty look at what's happening in both examples:
With example 1, the JS engine has to do the following:
Check the current scope to see if my_var exists.
Check the scope above (and the scope above that) until it finds my_var.
Create my_var in the global scope when it's not found.*
*Step 3 has not yet happened when you try to assign a value to my_var.
Example 2:
Is there a variable named my_var in the current scope? Yes, you just created it using the var keyword.
Assign its value.
In the 2nd situation, my var is undefined so the variable is assigned an empty object which is {}
Although I cannot quote the specs, I assume that the initialization in a var statement is just syntactic sugar:
var my_var = my_var || {};
is equivalent to:
var my_var;
my_var = my_var || {};
In the first line, my_var is declared and implicitely set to the special value undefined. Then, in the second line, my_var exists, undefined evaluates to false and no error is raised.
In your first example, however, my_var is unknown when the right hand side is evaluated, hence the error.
In the first case you try to assign a variable that was not defined. Its the same as you would write :
my_var = a || {};
in the second case my_var is only undefined as you use the var keyword an create my_var in the actual scope. Undefined is converted to false and it will return the empty object.
Interestingly, this will work:
a = my_var || {}; // 'a' is now an empty object
When you use the 'var' keyword you're literally giving the command "create a new variable and assign to it this value." If you don't use 'var' then you're implying that the variable already exists within the global scope somewhere.
In your example the JavaScript engine attempts to look up the current value of 'my_var', finds that it doesn't exist, cannot create it because you're currently attempting to assign a value to it, and fails.