What does the 'in' keyword in javascript mean? - javascript

I found this code:
if (!("aa" in window)) {
alert('oh my god');
var aa = 1;
}
alert("aa" in window);
alert(aa);
This code the second alert is alert true,but,the third alert is 'undefined',and the alert in the 'if' is not run. Why?
I think the reason is the in; what is its effect?
I searched on Google, but found nothing, because Google thinks the word ‘in&srquo; is a filter word.
We always use the in in loops, but, frankly speaking, I use it but don’t really understand it.

This tests if the window object has a property (filled or not) whose key is "aa".
This operator is very useful because it works even if the value is undefined :
window.aa = undefined; // or just aa=undefined if you're in the global scope
console.log('aa' in window); // logs true
It also works if the property isn't enumerable :
console.log('length' in []); // logs true
In your case, there may not be an aa value, but if the alert shows you true, the property was added to window.
MDN reference on in
Note that the for...in statement is different in that it doesn't really use the in operator but is a specific construct.
MDN reference on for...in
EDIT : an explanation of your edited question (very different from the first one) :
Your confusion seems to arise from the fact you declared the var aa = 1; in a block. You should know that the scope of a variable in JavaScript is either a function of the global scope and that declarations are hoisted. So your code is in fact equivalent to
var aa = undefined;
if (!("aa" in window)) { // aa is in window, so we don't enter here
alert('oh my god');
aa = 1;
}
alert("aa" in window); // yes, the property exists, it's true
alert(aa); // aa is still undefined

Taking the alerts in order:
alert #1 is never reached because ("aa" in window) === true so the if boolean condition is false.
JavaScript has function scope and the variable aa is "hoisted" up to the top of the scope first, so it is defined.
alert #2
"aa" in window is true because the variable was added to the window object when it was hoisted up. Equivalent to just writing:
var foo;
"foo" in window (which === true)
alert #3
From the Standard ECMA-262 ECMAScript Language Specification :
A variable statement declares variables that are created as defined in 10.5. Variables are initialised to undefined when created. A variable with an Initialiser is assigned the value of its AssignmentExpression when the VariableStatement is executed, not when the variable is created.
So aa is undefined since the assignment was never executed.

in checks if property exists in Object
// in the below snippet they are checking if 'aa' property exists in 'window' Object . Since variables are function declarations are hoisted. you'll never enter inside if block .
var aa = undefined ;
if (!("aa" in window)) { //2 => 'aa' property exists
alert('oh my god');
aa = 1; // 1 => hoisted
}

Related

Variables with the same name, but the local scope variable isn't being used, why?

Why is the declaration of the variable 'a' not used in the output of the console log of the below code? Doesn't that go against the scope chain? The variable 'a' with the undefined value on line 4 surely should be used on the console output on line 5?
var a = 15;
function checkScope(a) {
var a;
console.log(a); // log outputs 15 and not undefined
}
checkScope(a);
I want to understand this behaviour. To confirm, this behaviour has nothing to do with hoisting or even scope (i.e. scope chain)?
I don't believe scope is relevant to explain this behaviour because 'a' exists locally (its value is 'undefined' as it's not initialised) within the function, hence the Javascript engine will not look to the outer lexical environment to find 'a' (which has a value of 15). Or as per the MDN page: "The scope of a variable declared with var is its current execution context", which in this case is the enclosing function 'a'.
I also don't believe this behaviour is a result of hoisting as far as I know.
So, in addition, this is what is stated on the MDN page? "If you re-declare a JavaScript variable, it will not lose its value."?
Off-topic question but, what's the reason behind MDN's statement above? Is it simply related to memory management? There's no point to logical reason to allocate a new memory address every single time a variable is declared?
Now, going back to my question:
Since they're re-declared, If I'm interpreting MDN correctly, does that mean line 3 is basically ignored? But I don't think so because both variable are declared in their own, separate execution contexts, so surely the variable 'a' in line 4 is being used/accessed? Because the scope chain would suggest that the closest local variable would be used (i.e. the local 'a' with a value of undefined), and in addition, I would best think that the MDN statement applies to only re-declared variables only within the same lexical environment, correct?
I am just trying to work out whether 'a' in line 4 is actually used when we refer to 'a' in line 5? Or is line 3 ignored, and thus line 5 will instead access (refer to) the 'a' in line 3 (i.e. checkScope's 'a' parameter)?
- The latter sort of implies the former
It makes sense if line 3 from the above code is simply ignored, because deleting it achieves the same result:
var a = 15;
function checkScope(a) {
console.log(a); // log outputs 15 and not undefined
}
checkScope(a);
Thanks.
You have declared a variable named a three times.
Once as a global on line 1: var a = 15;
Twice inside the function:
Once with a var statement on line 4: var a;
Once with an argument definition on line 3: function checkScope(a) {
The line 4 var has no effect. The variable is already declared.
Then you call checkScope(a); which passes the value of the global a (15) to the local a argument of checkScope. This is why it is 15 and not undefined.
Since they're re-declared, If I'm interpreting MDN correctly, does that mean line 3 is basically ignored?
var a is basically ignored.
But I don't think so because both variable are declared in their own, separate execution contexts
This is where you are being tripped up by having three and not two declarations of a. It declares the variable defined by the function argument name.
If you redeclare a JavaScript variable, it will not lose its value.
take a look at this answer.
var a = 15;
function checkScope(a) {
var a; // this is equivalent to redeclaring the variable
console.log(a); // log outputs 15 and not undefined
}
checkScope(a);
Basically line 4
var a;
is where the compiler finds a redeclared variable of the function parameter. Because of the missing initializing, a keeps the value of the handed over value of the parameter a.
Consider 'a' to be different assigned variable for arguments in function and inside as a local variable.
function a != var a;
Now, some 'a' is called by console.log(a). Now, it will search for the default 'a' value if existing, i.e, 'a' of function. Even on manipulation of 'a',
function hoist(a) {
var a;
a*=2;
console.log(a);
}
hoist(10);
output: 20

Variables defined in global scope with identical names

Can anybody explain, why next js code rises two alert windows with 'string1' text rather than to rise the second with 'undefined' text inside?? If both variables are described in the same scope..
var a = 'string1';
alert(a);
var a;
alert(a);​
http://jsfiddle.net/FdRSZ/1/
Thanks
Variable declarations (and function declarations) are hoisted to the top of the scope in which they appear. Assignments happen in place. The code is effectively interpreted like this:
var a;
var a;
a = 'string1';
For example, consider what happens if you declare a variable inside an if statement body:
console.log(myVar); //undefined (NOT a reference error)
if (something === somethingElse) {
var myVar = 10;
}
console.log(myVar); //10
Because JavaScript does not have block scope, all declarations in each scope are hoisted to the top of that scope. If you tried to log some variable that was not declared, you would get a reference error. The above example is interpreted like this:
var myVar; //Declaration is hoisted
console.log(myVar);
if (something === somethingElse) {
myVar = 10; //Assignment still happens here
}
console.log(myVar);
So even if the condition evaluates to false, the myVar variable is still accessible. This is the main reason that JSLint will tell you to move all declarations to the top of the scope in which they appear.
In slightly more detail... this is what the ECMAScript 5 spec has to say (bold emphasis added):
For each VariableDeclaration and VariableDeclarationNoIn d in code, in
source text order do
Let dn be the Identifier in d.
Let
varAlreadyDeclared be the result of calling env’s HasBinding concrete
method passing dn as the argument.
If varAlreadyDeclared is false, then
Call env’s CreateMutableBinding concrete method passing dn and
configurableBindings as the arguments.
Call env’s SetMutableBinding concrete method passing dn, undefined, and strict as the arguments.
So, if a binding already exists with the identifier we are trying to bind now, nothing happens.
Thats because JavaScript does something called variable hoisting. In fact, your JS looks like this:
var a; // hoisted -> declared on top
a = 'string1';
alert(a);
alert(a);
See How Good C# Habits can Encourage Bad JavaScript Habits for more details on how JavaScript works.
That's because the second var a isn't a separate variable declaration. As far as the javascript interpreter is concerned it is the same a as the first one.
var means "Scope this variable to this function" not "Set the value of this variable to undefined".
If the variable is already scoped to the function then var foo means the same as just plain foo

How to distinguish between a variable that is not declared and a varrable that is declared but not be assigned any value?

Both scenario, the typeof the variable will be "undefined".
But undeclared variable will raise a exception.
Is there a easy way to handle this?
You may find the question (and my answer) in How to check if a variable or object is undefined? relevant. In general, I view any access to an "undeclared variable" a programming error.
However, this particular case can *only** be detected with the use of detecting for a ReferenceError exception. But, yuck, yuck, yuck! Remember variable declarations are a static lexical construct, ignoring the quirks with property-variables of the global object.
ReferenceError, and now "strict", exist for a reason and I suspect this is an X-Y problem. I do not even recommend the use of typeof for this purpose: fix the code :-)
Happy coding.
*It has been pointed out that "variable" in window will also [and only] work for global "variables" (they are really just properties that don't need be qualified in all contexts).
if property we want to check in object whether that it exists or not, even if its undefined.
we will use one of these:
'prop' in obj(to check for properties from prototype chain) or
obj.hasOwnProperty('prop')
we need to use methods above to check if property exists as accessing property that has not been declared in object will also return undefined.
var o={};
o.c=undefined;
o.c===undefined; //is true
o.a===undefined; //is true as well even though c exists while a doesn't
commonly not a problem as nobody really declare undefined properties much, but when do so do it like this.
o.c=''; //when it can be string or
o.c=null; //to clearly indicate that its nothing.
then
o.c === undefined will return false!
note!!!
null == undefined //true while
null === undefined //false that's why use three equals to test
For variables not declared and are not inside object. When accessed The compiler will return (reference)error.
If it doesn't it means its being treated as a global property, window object property, and was not declared, at least in all parent scope, so it will be undefined just as o.a was at top. it will become window.prop.
so x; //error
but x=3; //no error assumed to be global object.
just like o.abcd = 3; would...
make(declare) a property abcd in object o valued(assigned) 3 all at once.
To avoid properties to become a global variable we use var keyword inside function, like this var k;
One thing you can do about this catch the reference error when throw for a variable that doesn't exist and are thought to be a variable itself.
try {
x
} catch(e){//code to run when x is not declared let alone defined.}
You can try:
var a;
try {
a;
alert('a');
} catch(e) { /* a not defined */ }
try {
b;
alert('b');
} catch(e) { /* b not defined */ }
alert('done');
DEMO
You should never be attempting to access undeclared vars if you're writing clean JS. To avoid such pitfalls (among many others) start LINTing your JS with http://www.jslint.com/ or http://jshint.com/ .
A good read to help you understand the LINT tools and reasoning behind their findings is Crockford's Book, JavaScript: The Good Parts ( http://www.amazon.com/gp/aw/d/0596517742 ).

when I use global scope variable without 'var', its showing me Error. why?

See my example code below
<script>
alert(a); // undefined
alert(b); // It is Error, b is not defined.
var a=1;
b=10;
</script>
When both variable a and b are in global scope, why I am getting error message for b. But there is no error message for variable a ? what is the reason ?
can anyone please explain me ?
The first alert shows undefined because the var statements are hoisted to the top of the enclosing scope, in other words, var statements and function declarations are made before the actual code is executed, in the parsing stage.
When your code is executed, is equivalent to:
var a; // declared and initialized with `undefined` before the code executes
alert(a); // undefined
alert(b); // ReferenceError, b is not declared.
a=1;
b=10;
The second alert doesn't even executes, trying to access b gives you a ReferenceError because you never declared it, and you are trying to access it.
That's how the identifier resolution process works in Javascript, if an identifier is not found in all the scope chain, a ReferenceError exception is thrown.
Also, you should know that assigning an identifier without declaring it first (as b = 10) does not technically declares a variable, even in the global scope, the effect may be similar (and it seems to work), at the end the identifier ends as a property of the global object, for example:
var a = 1;
b = 10;
// Similar effect:
window.a; // 1
window.b; // 10
But this is just due the fact that the global object is the top-most environment record of the scope chain.
Another difference between the two above is that the identifier declared with var produces a non-configurable property on the global object (cannot be deleted), e.g.:
delete window.a; // false
delete window.b; // true
Also, if you are in the scope of a function, and you make an assignment to an undeclared identifier, it will end up being a property of the global object, just like in the above example, whereas the var statement will create a local variable, for example:
(function(){
var a = 1;
b = 10;
})();
typeof window.a; // 'undefined', was locally scoped in the above function
typeof window.b; // 'number', leaked, an unintentional global
I would really discourage make assignments to undeclared identifiers, always use var to declare your variables, moreover, this has been disallowed on ECMAScript 5 Strict Mode, assignments made to undeclared identifiers throw a ReferenceError:
(function(){'use strict'; b = 10;})(); // throws a ReferenceError

Difference between variable declaration syntaxes in Javascript (including global variables)?

Is there any difference between declaring a variable:
var a=0; //1
...this way:
a=0; //2
...or:
window.a=0; //3
in global scope?
Yes, there are a couple of differences, though in practical terms they're not usually big ones.
There's a fourth way, and as of ES2015 (ES6) there's two more. I've added the fourth way at the end, but inserted the ES2015 ways after #1 (you'll see why), so we have:
var a = 0; // 1
let a = 0; // 1.1 (new with ES2015)
const a = 0; // 1.2 (new with ES2015)
a = 0; // 2
window.a = 0; // 3
this.a = 0; // 4
Those statements explained
#1 var a = 0;
This creates a global variable which is also a property of the global object, which we access as window on browsers (or via this a global scope, in non-strict code). Unlike some other properties, the property cannot be removed via delete.
In specification terms, it creates an identifier binding on the object Environment Record for the global environment. That makes it a property of the global object because the global object is where identifier bindings for the global environment's object Environment Record are held. This is why the property is non-deletable: It's not just a simple property, it's an identifier binding.
The binding (variable) is defined before the first line of code runs (see "When var happens" below).
Note that on IE8 and earlier, the property created on window is not enumerable (doesn't show up in for..in statements). In IE9, Chrome, Firefox, and Opera, it's enumerable.
#1.1 let a = 0;
This creates a global variable which is not a property of the global object. This is a new thing as of ES2015.
In specification terms, it creates an identifier binding on the declarative Environment Record for the global environment rather than the object Environment Record. The global environment is unique in having a split Environment Record, one for all the old stuff that goes on the global object (the object Environment Record) and another for all the new stuff (let, const, and the functions created by class) that don't go on the global object.
The binding is created before any step-by-step code in its enclosing block is executed (in this case, before any global code runs), but it's not accessible in any way until the step-by-step execution reaches the let statement. Once execution reaches the let statement, the variable is accessible. (See "When let and const happen" below.)
#1.2 const a = 0;
Creates a global constant, which is not a property of the global object.
const is exactly like let except that you must provide an initializer (the = value part), and you cannot change the value of the constant once it's created. Under the covers, it's exactly like let but with a flag on the identifier binding saying its value cannot be changed. Using const does three things for you:
Makes it a parse-time error if you try to assign to the constant.
Documents its unchanging nature for other programmers.
Lets the JavaScript engine optimize on the basis that it won't change.
#2 a = 0;
This creates a property on the global object implicitly. As it's a normal property, you can delete it. I'd recommend not doing this, it can be unclear to anyone reading your code later. If you use ES5's strict mode, doing this (assigning to a non-existent variable) is an error. It's one of several reasons to use strict mode.
And interestingly, again on IE8 and earlier, the property created not enumerable (doesn't show up in for..in statements). That's odd, particularly given #3 below.
#3 window.a = 0;
This creates a property on the global object explicitly, using the window global that refers to the global object (on browsers; some non-browser environments have an equivalent global variable, such as global on NodeJS). As it's a normal property, you can delete it.
This property is enumerable, on IE8 and earlier, and on every other browser I've tried.
#4 this.a = 0;
Exactly like #3, except we're referencing the global object through this instead of the global window. This won't work in strict mode, though, because in strict mode global code, this doesn't have a reference to the global object (it has the value undefined instead).
Deleting properties
What do I mean by "deleting" or "removing" a? Exactly that: Removing the property (entirely) via the delete keyword:
window.a = 0;
display("'a' in window? " + ('a' in window)); // displays "true"
delete window.a;
display("'a' in window? " + ('a' in window)); // displays "false"
delete completely removes a property from an object. You can't do that with properties added to window indirectly via var, the delete is either silently ignored or throws an exception (depending on the JavaScript implementation and whether you're in strict mode).
Warning: IE8 again (and presumably earlier, and IE9-IE11 in the broken "compatibility" mode): It won't let you delete properties of the window object, even when you should be allowed to. Worse, it throws an exception when you try (try this experiment in IE8 and in other browsers). So when deleting from the window object, you have to be defensive:
try {
delete window.prop;
}
catch (e) {
window.prop = undefined;
}
That tries to delete the property, and if an exception is thrown it does the next best thing and sets the property to undefined.
This only applies to the window object, and only (as far as I know) to IE8 and earlier (or IE9-IE11 in the broken "compatibility" mode). Other browsers are fine with deleting window properties, subject to the rules above.
When var happens
The variables defined via the var statement are created before any step-by-step code in the execution context is run, and so the property exists well before the var statement.
This can be confusing, so let's take a look:
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar); // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar); // displays "b"
Live example:
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar); // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar); // displays "b"
function display(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
As you can see, the symbol foo is defined before the first line, but the symbol bar isn't. Where the var foo = "f"; statement is, there are really two things: defining the symbol, which happens before the first line of code is run; and doing an assignment to that symbol, which happens where the line is in the step-by-step flow. This is known as "var hoisting" because the var foo part is moved ("hoisted") to the top of the scope, but the foo = "f" part is left in its original location. (See Poor misunderstood var on my anemic little blog.)
When let and const happen
let and const are different from var in a couple of ways. The way that's relevant to the question is that although the binding they define is created before any step-by-step code runs, it's not accessible until the let or const statement is reached.
So while this runs:
display(a); // undefined
var a = 0;
display(a); // 0
This throws an error:
display(a); // ReferenceError: a is not defined
let a = 0;
display(a);
The other two ways that let and const differ from var, which aren't really relevant to the question, are:
var always applies to the entire execution context (throughout global code, or throughout function code in the function where it appears), but let and const apply only within the block where they appear. That is, var has function (or global) scope, but let and const have block scope.
Repeating var a in the same context is harmless, but if you have let a (or const a), having another let a or a const a or a var a is a syntax error.
Here's an example demonstrating that let and const take effect immediately in their block before any code within that block runs, but aren't accessible until the let or const statement:
var a = 0;
console.log(a);
if (true)
{
console.log(a); // ReferenceError: a is not defined
let a = 1;
console.log(a);
}
Note that the second console.log fails, instead of accessing the a from outside the block.
Off-topic: Avoid cluttering the global object (window)
The window object gets very, very cluttered with properties. Whenever possible, strongly recommend not adding to the mess. Instead, wrap up your symbols in a little package and export at most one symbol to the window object. (I frequently don't export any symbols to the window object.) You can use a function to contain all of your code in order to contain your symbols, and that function can be anonymous if you like:
(function() {
var a = 0; // `a` is NOT a property of `window` now
function foo() {
alert(a); // Alerts "0", because `foo` can access `a`
}
})();
In that example, we define a function and have it executed right away (the () at the end).
A function used in this way is frequently called a scoping function. Functions defined within the scoping function can access variables defined in the scoping function because they're closures over that data (see: Closures are not complicated on my anemic little blog).
Keeping it simple :
a = 0
The code above gives a global scope variable
var a = 0;
This code will give a variable to be used in the current scope, and under it
window.a = 0;
This generally is same as the global variable.
<title>Index.html</title>
<script>
var varDeclaration = true;
noVarDeclaration = true;
window.hungOnWindow = true;
document.hungOnDocument = true;
</script>
<script src="external.js"></script>
/* external.js */
console.info(varDeclaration == true); // could be .log, alert etc
// returns false in IE8
console.info(noVarDeclaration == true); // could be .log, alert etc
// returns false in IE8
console.info(window.hungOnWindow == true); // could be .log, alert etc
// returns true in IE8
console.info(document.hungOnDocument == true); // could be .log, alert etc
// returns ??? in IE8 (untested!) *I personally find this more clugy than hanging off window obj
Is there a global object that all vars are hung off of by default? eg: 'globals.noVar declaration'
Bassed on the excellent answer of T.J. Crowder: (Off-topic: Avoid cluttering window)
This is an example of his idea:
Html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="init.js"></script>
<script type="text/javascript">
MYLIBRARY.init(["firstValue", 2, "thirdValue"]);
</script>
<script src="script.js"></script>
</head>
<body>
<h1>Hello !</h1>
</body>
</html>
init.js (Based on this answer)
var MYLIBRARY = MYLIBRARY || (function(){
var _args = {}; // private
return {
init : function(Args) {
_args = Args;
// some other initialising
},
helloWorld : function(i) {
return _args[i];
}
};
}());
script.js
// Here you can use the values defined in the html as if it were a global variable
var a = "Hello World " + MYLIBRARY.helloWorld(2);
alert(a);
Here's the plnkr. Hope it help !
In global scope there is no semantic difference.
But you really should avoid a=0 since your setting a value to an undeclared variable.
Also use closures to avoid editing global scope at all
(function() {
// do stuff locally
// Hoist something to global scope
window.someGlobal = someLocal
}());
Always use closures and always hoist to global scope when its absolutely neccesary. You should be using asynchronous event handling for most of your communication anyway.
As #AvianMoncellor mentioned there is an IE bug with var a = foo only declaring a global for file scope. This is an issue with IE's notorious broken interpreter. This bug does sound familiar so it's probably true.
So stick to window.globalName = someLocalpointer

Categories

Resources