When I run the following simple Javascript line...console logs an error.
console.log(abc);
But when I run the above line like
console.log(this.abc); or console.log(window.abc);
the console does not throw an error. Instead it prints "undefined".
Why?
Note: 'abc' variable is not defined or declared.
It's not errornous to refer to a non-existent property, but it is erronous to refer to a standalone variable name which doesn't exist.
When one references a non-existent property on an object, undefined will be returned - that's how how things work. But standalone variable names, on the other hand, do need to be defined before referring to them, in almost all situations. Failing to define a standalone variable before trying to refer to it will throw a ReferenceError in all but 2 situations:
(1) When using typeof
console.log(typeof foo);
(2) When assigning to such a variable in non-strict mode (the variable will be implicitly created on the global object):
const arr = [1, 2, 3];
for (i = 0; i < arr.length; i++) {
// if in sloppy mode, and i hasn't been defined beforehand,
// it will be created as a global variable
}
console.log(typeof i);
If you try to assign to such a variable in strict mode when it hasn't been declared beforehand, an error will be thrown.
When you looking for a variable
console.log(abc);
Is not defined and should throw
Uncaught ReferenceError: abc
is not defined in any context at all
however
console.log(this.abc) and console.log(window.abc)
part of it is defined
console.log(this)
console.log(window)
return current objects instance and window objects respectively and have a reference point. the plain console.log(abc) has no reference point
actually it's not a variable. It is a key which is inside an object. (At this point the object is this or window). this and window created from JavaScript.
It's an interesting question to ask!.
To be able to understand this, we must understand Variable Hoisting in Jaascript.
if you want an undefined for a variable that is not declared yet , well the following would work!
console.log(abc)
var abc = 'ss';
So, here if we try to access a declared variable before it is initialized then undefined is actually assigned at the top of function execution. in other words, all the variables are hoisted to the top of their immediate scope level and are assigned undefined until they reach the initialization point.
to give you a blunt answer, trying to use an undeclared variable would give you Reference Error while trying to access a declared variable before the initialization would give youundefined
and, for objects like this and window well they are available objects . so basically at this point people say, In Javascript everything is present, meaning, trying to access a property that is not yet there in a js object would give you undefined.
On most browsers and Javascript environments that respect Javascript specification (this may change in other javascript environments where there is no console):
Any property that has not been assigned a value or non existent property (or a function without a return statement) returns undefined.
In the first examples, the dot operator is being called. The behaviour in case you access a non existent property is defined and it is that to return undefined, which is a valid js type. Therefore undefined is being logged.
On the last example, on the other hand, the non existent variable throws a ReferenceError. This happens directly, as unlike the first case, no context has been accessed, no dot operator is being called and this is just a plain error.
It is the normal JavaScript behavior.
Lets consider a variable name
var name;
console.log(name);
The above wont throw an error, because the variable name was declared before using it in console.log.
console.log(name);
This will throw a reference error because you did not declare the variable first.
But,
If name is accessed from an already defined variable( e.g. window, this ), it wont throw an error whether defined or not. Just like the below will simply print undefined, reference error wont be thrown.
console.log(window.name);
Note that window is already defined by the browser.
Notwithstanding,
console.log(window_a.name);
the above will throw a reference error because name is being accessed on an undefined variable window_a.
var window_a = {};
console.log(window_a.name);
This wont throw reference error because window_a is now declared.
Related
When using JavaScript's with statement, where do variables that have invalid names go?
var o = {"##$%":1,"test":2}
with(o){
console.log(test)
// Can't do this:
//console.log(##$%)
// Was it not imported, or is it just inaccessible?
}
Can you reference the code in a JavaScript engine as well?
If a property is not a valid identifier, it can't be referenced like an identifier inside with. It's not inaccessible, but your only option is to look up the property on the original object manually, like normal:
var o = {"##$%":1,"test":2}
with(o){
console.log(o['##$%']);
}
This sort of issue is not exclusive to the deprecated with statement. It occurs with the global object as well. Just like a with statement creates an object Environment Record, similarly, all code in a script is, in a sense, implicitly wrapped in a with for the global object (resulting in the global environment record).
So, for exactly the same reasons, when a property which can't be an identifier is on window, eg:
window['###'] = 'foo';
There's no way to get to foo by using a standalone identifier without explicitly referencing window first (or use some other method to get to the global object).
(of course, just like with with, properties which are valid as identifiers on window can be referenced standalone - that's why we can, for example, reference undefined and Array instead of window.undefined and window.Array. This can cause bugs...)
Where do variables […] go?
I think you have this backwards. A with statement doesn't create any variables (like a var declaration would), instead it changes the scope so that any identifier is looked up as a property on the object. Every time you access xyz, it looks if ('xyz' in o) return o.xyz else … - that's why with statements are so slow and deprecated in strict mode.
So there are no "variables that have invalid names" at all. If you used an invalid identifier in the first place, it would have thrown a syntax error and the code wouldn't even run.
Mozilla says that variables are properties of the global object. If an object has a property that isn't defined, then trying to access it does not create a reference exception - it simply returns that the property is not defined.
If there is such a global object - then why does accessing its properties (ie: variables) that do not exist create reference errors? What is precisely the difference between these two scenarios?
Example:
console.log(x) //x is not declared -> reference error
var x = new Object();
console.log(x.property); //console.log: undefined
tl;dr: The way the variable is accessed makes all the difference, not how it is stored.
First some background:
There are basically two ways how variables are "stored".
In a declarative environment, variables are stored in an internal data structure that is not accessible from user code.
In an object environment, variables are stored as properties of a user code accessible object. The global environment happens to be an object environment (it's a bit more complicated than that but lets keep it simple). Therefore global variables are properties of the global object.
So why does accessing a non-existing global variable throw an error? Because it is not relevant how the variables are stored, only how the are accessed.
foo and window.foo are simply two different ways of accessing a global variable.
The language rules for evaluating a variable (foo) explicitly say that if the variable doesn't exist, throw a reference error (again, no matter how it is stored).*
The language rules for evaluating property access (window.foo) say that if the property doesn't exist, undefined should be returned.
And if you think about, this makes much more sense from a consistency perspective. Accessing foo should have the same result, no matter whether the variable is stored in a declarative environment or an object environment.
*: To be more precise: It's the GetValue function that causes the error to be thrown. GetValue is called almost everywhere when resolving a variable (exceptions are typeof and the grouping operator (...)).
I try to understand why?
Variable a is not defined and i didn't assign any value to it.
however, if i call a, it returns exception, but a is a var of window object. If i call a like window.a it returns undefined.
below screenshot is.
why so?
screenshot
In first case there is no existence of a.
You have neither declared a.
So js have no idea of a. When ever you are trying to access a no existence variable it will throw a ReferenceError
In second case you are trying to find a property called a in the window object. window.a will check if there is any property a defined on window. If it is not it will return undefined
In JavaScript in the browser window is the global object, which means every variable defined in the global scope is a child of window. So why do I get this result:
console.log(window.foo); // No error, logs "undefined".
console.log(foo); // Uncaught ReferenceError: foo is not defined.
Fiddle
Those two lines should be the same, shouldn't they?
Because with window.foo you are explicitly looking for foo property of window object which is not the case in latter option. In the latter option, if foo isn't defined, you should as developer be able to know that it isn't defined and get the clear error warning rather than interpreter setting it to undefined on its own (like first case) which will lead to unexpected results.
Reference Error:
Represents an error when a non-existent variable is referenced.
A ReferenceError is thrown when trying to dereference a variable that has not been declared.
Take a look at this article for more info:
Understanding JavaScript’s ‘undefined’
Quoting from above article:
A Reference is considered unresolvable if its base value is undefined. Therefore a property reference is unresolvable if the value before the dot is undefined. The following example would throw a ReferenceError but it doesn’t because TypeError gets there first. This is because the base value of a property is subject to CheckObjectCoercible (ECMA 5 9.10 via 11.2.1) which throws a TypeError when trying to convert Undefined type to an Object.
Examples:
var foo;
foo.bar; //TypeError (base value, foo, is undefined)
bar.baz; //ReferenceError (bar is unersolvable)
undefined.foo; //TypeError (base value is undefined)
References which are neither properties or variables are by definition unresolvable and will throw a ReferenceError, So:
foo; //ReferenceError
In your first example (window.foo) you are accessing a property of the window object. JavaScript returns "undefined" for when you are trying to access a non existent property of a object. It's designed that way.
In the second example you are referencing a variable directly, and since it does not exists an error is raised.
It's just the way JavaScript is designed and works.
In JavaScript you can assign object fields on the fly like that, so window.foo is nearly (see comments below) equivalent to var foo; when defined in the global context, whereas just calling foo out of the blue makes the browser panic 'cause it down't even know which object to look in. Notice, if you do:
//when in global context, 'var' sets a property on the window object
var foo;
console.log(foo);
//it will then also log `undefined` instead of throwing the error.
//if you then do:
foo = "abbazabba";
console.log(window.foo);
// it will return "abbazabba"
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 ).