Playing with javascript closures I end up with this question I cannot reach to explain.
(function() {
console.log("Inside closure"); //does not work
}(foo));
It does not work because foo is undefined. referenceError
But if prior I set var foo = undefined; it works (tested on Chrome and ff).
It is not the same to be undefined that to be set to undefined?
example in jsfiddle
In javaScript, 'undefined' is one of the primitive data types. It represents the type of an object.
var a = undefined;
var b;
console.log((typeof(a)));
console.log((typeOf(b)));
The output will be undefined for both the cases.
If you don't declare a variable at all and try to access it, the error thrown will be the following. I tried to access c which is not declared at all.
Uncaught ReferenceError: c is not defined(…)
Having a variable whose value is undefined is not the same as having no variable with that name.
In ECMAScript, identifiers are resolved according to Identifier Resolution, which returns a reference given by GetIdentifierReference.
In case the variable doesn't exist, the base value of that reference will be undefined, otherwise it will be an environment record.
When GetValue gets the value of that reference, it will check IsUnresolvableReference. If the base value is undefined, it will return false, and GetValue will throw a ReferenceError exception.
If the variable exists (even if its value is undefined), GetValue will return its value.
If you are not sure whether some variable exists, you can use the typeof operator, which returns "undefined" for unresolvable references instead of throwing.
If the question is:
But what if somebody uses the the common jQuery wrapper and has the jQuery script not working yet?
Then you will still get a reference error if the jQuery identifier is not in the global scope because it is trying to find the reference to jQuery but it will not exist.
the undefined keyword is passed in the closure so that if undefined is assigned a value, it will not mess with your code. For example:
var undefined = 123
if(undefined){
console.log("pass")
}
this code will pass. If you Pass through undefined but leave out the parameter when you invoke it, undefined will have not a value assigned to it. It wont be looking for a reference as you haven't assigned the parameter For example :
(function(undefined){
// undefined will be undefined.
}())
I've done a quick example here for you : https://jsfiddle.net/gn7h3641/
TLDR : if your asking JavaScript for the value of a variable that doesn't exist(not been defined with var), it will explode because it has not got a reference to find the value yet which is different to checking if something is undefined in a 'if(test === undefined)'
Related
I have this very simple question, but I can not find any complete answer for this question.
JavaScript's null and undefined is the values of variables that have not been initialised and the value you get when you query the value of an object property or an array element that does not exist.
I first thought we get a referenceerror when we attempt to access a non-existent property of an object or an array element that does not exist, but as it turns out it isn't the case.
But on which occasions actually does it throw a referenceerror?
I appreciate if someone can tell all the situations when it can throw a referenceerror
You get a reference error when you:
Attempt to read a variable that has not been declared
Attempt to write to a variable that has not been declared when working in Strict Mode (in legacy mode this will create an implicit global instead)
JavaScript's null and undefined is the values of variables that have not been initialised
No. A variable that has been declared but not assigned a value or a property that has not been assigned a value will have undefined as a default value. undefined can also be explicitly assigned. null can only be explicitly assigned.
Considering the following code:
//the var Test has NOT been declared yet
console.log((typeof Test)); // "undefined"
console.log(Test); //"Uncaught ReferenceError: Test is not defined"
Why does the second console.log statement throw a ReferenceError and the first displays undefined.
Because test is undefined.
In that first console.log you're asking the system to tell you the type of a variable. So it looks through the current scope chain to find a reference to that variable so it may infer its type.
When it doesn't find the variable, it receives the undefined primitive. Which has a type, as I'm sure you've guessed, of undefined.
The second time you're asking it to print out the value of an undefined variable. Since the variable is not defined (there is no reference to it in the current scope chain), this is an error you're trying to ACCESS DATA that doesn't exist, not just infer its type.
So,
I have always used the type of construction for testing the presence of variables:
if(foo){
doThings();
}
Now, I'm getting an
Uncaught ReferenceError: foo is undefined
Here's a fiddle
it's a fact that the var was never even declared.
My question is, is this normal behaviour? I've used this many times and i think this is not the first time the variable is not declared; i'm almost sure that i never had a problem with this, it just returned false and didn't get in the condition.
Any help and clarification is welcome.
If a variable has not been declared then an attempt to reference it will result in a reference error.
If a variable has been declared but not assigned a value then it will implicitly have the value undefined and your code will work as expected.
In your case, this is what happens:
Evaluate the if statement [if ( Expression ) Statement]
This involves evaluating Expression, which returns a reference, as per 10.3.1
Call GetValue on the returned reference
If the reference is not resolvable (it's value is undefined), throw a reference error
Coerce the value of the reference to a boolean value
The algorithm for determining the value of a reference traverses the chain of nested lexical environments until it reaches the outermost context. When it reaches that point and still does not find a binding for the provided identifier it returns a reference whose base value is undefined.
When the base value of a reference is undefined that reference is said to be "unresolvable", and when a reference is unresolvable any attempt to reference it will result (unsurprisingly) in a reference error.
check the updated fiddle. If you haven't declare a variable then in condition u will have to check its type.
var a = 1;
var b;
try{
if(typeof(c)!='undefined') {
alert("OK");
}
} catch(ex){
alert(ex);
}
fiddle
var is a reserved keyword in Javascript.
The following is the corresponding error
Uncaught SyntaxError: Unexpected token var
I have seen different code examples with variables declared and set to undefined and null. Such as:
var a; // undefined - unintentional value, object of type 'undefined'
var b = null; // null - deliberate non-value, object of type 'object'
If the code to follow these declarations assigns a value to a or to b, what is the reason for using one type of declaration over another?
The first example doesn't assign anything to the variable, so it implicitly refers to the undefined value (see 10.5 in the spec for the details). It is commonly used when declaring variables for later use. There is no need to explicitly assign anything to them before necessary.
The second example is explicitly assigned null (which is actually of type null, but due to a quirk of the JavaScript specification, claims to have type "object"). It is commonly used to clear a value already stored in an existing variable. It could be seen as more robust to use null when clearing the value since it is possible to overwrite undefined, and in that situation assiging undefined would result in unexpected behaviour.
As an aside, that quirk of null is a good reason to use a more robust form of type checking:
Object.prototype.toString.call(null); // Returns "[object Null]"
I just saw this link which clarified my question.
What reason is there to use null instead of undefined in JavaScript?
Javascript for Web Developers states "When defining a variable that is meant to later hold an object, it is advisable to initialize the variable to null as opposed to anything else. That way, you can explicitly check for the value null to determine if the variable has been filled with an object reference at a later time."
I don't think there's a particular better way of doing things, but I'm inclined to avoid undefined as much as possible. Maybe it's due to a strong OOP background.
When I try to mimic OOP with Javascript, I would generally declare and initialize explicitly my variables to null (as do OOP languages when you declare an instance variable without explicitly initializing it).
If I'm not going to initialize them, why even declare them in the first place? When you debug, if you haven't set a value for a variable you watch, you will see it as undefined whether you declared it or not...
I prefer keeping undefined for specific behaviours:
when you call a method, any argument you don't provide would have an undefined value. Good way of having an optional argument, implementing a specific behaviour if the argument is not defined.
lazy init... in my book undefined means "not initialized: go fetch the value", and null means "initialized but the value was null (eg maybe there was a server error?)"
arrays: myArray[myKey] === null if there is a null value for this key, undefined if a value has never been set for this key.
Be careful though, that myVar == null and myVar == undefined return the same value whether myVar is undefined, null or something else. Use === if you want to know if a variable is undefined.
I would explicitly choose null, to not create an object whose id is later overwritten anyway:
var foo = {}; // empty object, has id etc.
var foo2 = null; // good practice, // filled with an object reference at a later time
var foo3;// undefined, I would avoid it
console.log(typeof foo);
console.log(typeof foo2);
console.log(typeof foo3);
Setting null also ensures good readability to identify the datatype (object),
results in
object
object
undefined
Source (Professional JavaScript for Web Developers 3rd Edition):
When defining a variable that is meant to later hold an object, it is
advisable to initialize the variable to null as opposed to anything
else. That way, you can explicitly check for the value null to
determine if the variable has been filled with an object reference at
a later time, such as in this example:
if (foo2 != null){
//do something with foo2
}
The value undefined is a derivative of null, so ECMA-262 defines them to be superficially equal as follows:
console.log(null == undefined); // prints true
console.log(null === undefined);// prints false
null is an object.. When something is undefined it is nothing.. it is not an object, neither a string, because it hasn't been defined yet.. obviously.. then it is simply a property with no function..
example:
You declare a variable with var but never set it.
var foo;
alert(foo); //undefined.
You attempt to access a property on an object you've never set.
var foo = {};
alert(foo.bar); //undefined
You attempt to access an argument that was never provided.
function myFunction (foo) {
alert(foo); //undefined.
}
Everything I've ever read indicates that in Javascript, the boolean value of an undefined variable is False. I've used code like this hundreds of times:
if (!elem) {
...
}
with the intent that if "elem" is undefined, the code in the block will execute. It usually works, but on occasion the browser will throw an error complaining about the undefined reference. This seems so basic, but I can't find the answer.
Is it that there's a difference between a variable that has not been defined and one that has been defined but which has a value of undefined? That seems completely unintuitive.
What is a ReferenceError?
As defined by ECMAScript 5, a ReferenceError indicates that an invalid reference has been detected. That doesn't say much by itself, so let's dig a little deeper.
Leaving aside strict mode, a ReferenceError occurs when the scripting engine is instructed to get the value of a reference that it cannot resolve the base value for:
A Reference is a resolved name binding. A Reference consists of three
components, the base value, the referenced name and the Boolean valued
strict reference flag. The base value is either undefined, an Object,
a Boolean, a String, a Number, or an environment record (10.2.1). A
base value of undefined indicates that the reference could not be
resolved to a binding. The referenced name is a String.
When we are referencing a property, the base value is the object whose property we are referencing. When we are referencing a variable, the base value is unique for each execution context and it's called an environment record. When we reference something that is neither a property of the base object value nor a variable of the base environment record value, a ReferenceError occurs.
Consider what happens when you type foo in the console when no such variable exists: you get a ReferenceError because the base value is not resolvable. However, if you do var foo; foo.bar then you get a TypeError instead of a ReferenceError -- a subtle perhaps but very significant difference. This is because the base value was successfully resolved; however, it was of type undefined, and undefined does not have a property bar.
Guarding against ReferenceError
From the above it follows that to catch a ReferenceError before it occurs you have to make sure that the base value is resolvable. So if you want to check if foo is resolvable, do
if(this.foo) //...
In the global context, this equals the window object so doing if (window.foo) is equivalent. In other execution contexts it does not make as much sense to use such a check because by definition it's an execution context your own code has created -- so you should be aware of which variables exist and which do not.
Checking for undefined works for variables that have no value associated but if the variable itself hasn't been declared you can run into these reference issues.
if (typeof elem === "undefined")
This is a far better check as doesn't run the risk of the reference issue as typeof isn't a method but a keyword within JavaScript.
Is it that there's a difference between a variable that has not been defined and one that has been defined but which has a value of undefined?
Yes. A undeclared variable will throw a ReferenceError when used in an expression, which is what you're seeing.
if (x) { // error, x is undeclared
}
Compared to;
var y; // alert(y === undefined); // true
if (y) { // false, but no error
}
That seems completely unintuitive.
Meh... what I find unintuitive:
if (y) // error, y is undeclared
var x = {};
if (x.someUndeclaredAttribute) // no error... someUndeclaredAttribute is implictly undefined.
Here's an example of Jon's explanation regarding environment records:
var bar = function bar() {
if (!b) { // will throw a reference error.
}
},
foo = function foo() {
var a = false;
if (a) {
var b = true;
}
if (!b) { // will not throw a reference error.
}
};
In strict mode, it is an error:
function a() {
"use strict";
if (!banana) alert("no banana"); // throws error
}
It's always really been better to make an explicit test for globals:
if (!window['banana']) alert("no banana");
It doesn't make sense to perform such a test for non-global variables. (That is, testing to see whether the variable is defined that way; it's fine to test to see whether a defined variable has a truthy value.)
edit I'll soften that to say that it rarely makes sense to thusly test for the existence of non-globals.
When a variable is declared and not initialized or it's used with declaration, its value is "undefined". The browser complains exactly when this undefined variable is referenced. Here "reference" means some piece of javascript code is trying to visit an attribute or method of it. For example, if "elem" is undefined, this will throw an exception:
elem.id = "BadElem";
or you use try/catch:
try { x } catch(err){}
This way you're not doing anything in case of an error but at least your script won't jump off the cliff...
undefined = variable exists but has no value in it
ReferenceError = variable does not exist