The console will print the result of evaluating an expression. The result of evaluating console.log() is undefined since console.log does not explicitly return something. It has the side effect of printing to the console.
You can observe the same behaviour with many expressions:
> var x = 1;
undefined;
A variable declaration does not produce a value so again undefined is printed to the console.
As a counter-example, expressions containing mathematical operators do produce a value which is printed to the console instead of undefined:
> 2 + 2;
4
Answer from James Allardice on Stack OverflowThe console will print the result of evaluating an expression. The result of evaluating console.log() is undefined since console.log does not explicitly return something. It has the side effect of printing to the console.
You can observe the same behaviour with many expressions:
> var x = 1;
undefined;
A variable declaration does not produce a value so again undefined is printed to the console.
As a counter-example, expressions containing mathematical operators do produce a value which is printed to the console instead of undefined:
> 2 + 2;
4
The undefined is the return value of console.log(). This is the standard behavior of Chrome, Safari, and Firefox JS Consoles.
Videos
var a = "a";
--function b(){
---- console.log(a);
---- var a = "a1";
---- console.log(a);
--}
b();
Outcome is
-- undefined a1
It prints the result of this expression - which is undefined. And yes, var a is a valid expression on its own.
Actually, you should rather be amused by why console prints undefined when you write var a = 3 or something like this. It also prints undefined if function anyFunctionName() {} statement is processed. In fact, all the var and function declaration (!) statements seem to be ignored if there's another statement with some 'real' result:
>>> var a = 3;
undefined
>>> var a = 3; a = 4;
4
>>> var a = 3; a = 4; var a = 5; function f() {};
4 // !!!
Now, I suppose the real reason behind is behaviour of eval statement, as described here:
- Let
resultbe the result of evaluating the programprog.- If
result.typeisnormaland its completion value is avalue V, then return thevalue V.- If
result.typeisnormaland its completion value isempty, then return the valueundefined.
So now the question is, what does var a = 4 statement return? Guess what: it's not 4.
The production VariableStatement : var VariableDeclarationList; is evaluated as follows:
- Evaluate VariableDeclarationList.
- Return (normal, empty, empty).
Now the most interesting part: what happened in the last example, why 4 is the result? That's explained in this section:
The production Program : SourceElements is evaluated as follows:
- Let result be the result of evaluating SourceElements.
[...]
The production SourceElements : SourceElements *SourceElement* is evaluated as follows:
- Let headResult be the result of evaluating SourceElements.
- If headResult is an abrupt completion, return headResult.
- Let tailResult be result of evaluating SourceElement.
- If tailResult.value is empty, let V = headResult.value, otherwise let V = > tailResult.value.
- Return (tailResult.type, V, tailResult.target)
Both function f() {} and var a = 5 statements' return values were (normal, empty, empty). So the script ended up with giving out the result of the first statement (starting from the script's end, so technically it's the last one) that's not (normal, empty, empty). That is the result of a = 4 assignment statement - which is 4.
P.S. And now for some icing on the cake: consider the following:
>>> function f() {}
undefined
>>> (function f() {})
function f() {}
The difference is quite subtle: the first input is treated as a Function Declaration statement, which, according to this rule...
The production SourceElement : FunctionDeclaration is evaluated as follows:
- Return (normal, empty, empty).
... will eventually produce undefined when eval-ed, as we already know.
The second input, however, is treated as a Function Expression, which is evaluated to the function itself. That means it'll be passed through eval and eventually returned to the console (in its format).
var a=1;
a
gives:
1
while
var a=1;
gives:
undefined
in the first case the console evaluates a so it prints the value of a
in the second case the console does not evaluate the value of a, but it evaluates the expression itself.
If you are interested in finding out whether a variable has been declared regardless of its value, then using the in operator is the safest way to go. Consider this example:
// global scope
var theFu; // theFu has been declared, but its value is undefined
typeof theFu; // "undefined"
But this may not be the intended result for some cases, since the variable or property was declared but just not initialized. Use the in operator for a more robust check.
"theFu" in window; // true
"theFoo" in window; // false
If you are interested in knowing whether the variable hasn't been declared or has the value undefined, then use the typeof operator, which is guaranteed to return a string:
if (typeof myVar !== 'undefined')
Direct comparisons against undefined are troublesome as undefined can be overwritten.
window.undefined = "foo";
"foo" == undefined // true
As @CMS pointed out, this has been patched in ECMAScript 5th ed., and undefined is non-writable.
if (window.myVar) will also include these falsy values, so it's not very robust:
false 0 "" NaN null undefined
Thanks to @CMS for pointing out that your third case - if (myVariable) can also throw an error in two cases. The first is when the variable hasn't been defined which throws a ReferenceError.
// abc was never declared.
if (abc) {
// ReferenceError: abc is not defined
}
The other case is when the variable has been defined, but has a getter function which throws an error when invoked. For example,
// or it's a property that can throw an error
Object.defineProperty(window, "myVariable", {
get: function() { throw new Error("W00t?"); },
set: undefined
});
if (myVariable) {
// Error: W00t?
}
I personally use
myVar === undefined
Warning: Please note that === is used over == and that myVar has been previously declared (not defined).
I do not like typeof myVar === "undefined". I think it is long winded and unnecessary. (I can get the same done in less code.)
Now some people will keel over in pain when they read this, screaming: "Wait! WAAITTT!!! undefined can be redefined!"
Cool. I know this. Then again, most variables in Javascript can be redefined. Should you never use any built-in identifier that can be redefined?
If you follow this rule, good for you: you aren't a hypocrite.
The thing is, in order to do lots of real work in JS, developers need to rely on redefinable identifiers to be what they are. I don't hear people telling me that I shouldn't use setTimeout because someone can
window.setTimeout = function () {
alert("Got you now!");
};
Bottom line, the "it can be redefined" argument to not use a raw === undefined is bogus.
(If you are still scared of undefined being redefined, why are you blindly integrating untested library code into your code base? Or even simpler: a linting tool.)
Also, like the typeof approach, this technique can "detect" undeclared variables:
if (window.someVar === undefined) {
doSomething();
}
But both these techniques leak in their abstraction. I urge you not to use this or even
if (typeof myVar !== "undefined") {
doSomething();
}
Consider:
var iAmUndefined;
To catch whether or not that variable is declared or not, you may need to resort to the in operator. (In many cases, you can simply read the code O_o).
if ("myVar" in window) {
doSomething();
}
But wait! There's more! What if some prototype chain magic is happening…? Now even the superior in operator does not suffice. (Okay, I'm done here about this part except to say that for 99% of the time, === undefined (and ****cough**** typeof) works just fine. If you really care, you can read about this subject on its own.)
Try
if (!window.console) console = ...
An undefined variable cannot be referred directly. However, all global variables are attributes of the same name of the global context (window in case of browsers), and accessing an undefined attribute is fine.
Or use if (typeof console === 'undefined') console = ... if you want to avoid the magic variable window, see @Tim Down's answer.
Paste the following at the top of your JavaScript (before using the console):
/**
* Protect window.console method calls, e.g. console is not defined on IE
* unless dev tools are open, and IE doesn't define console.debug
*
* Chrome 41.0.2272.118: debug,error,info,log,warn,dir,dirxml,table,trace,assert,count,markTimeline,profile,profileEnd,time,timeEnd,timeStamp,timeline,timelineEnd,group,groupCollapsed,groupEnd,clear
* Firefox 37.0.1: log,info,warn,error,exception,debug,table,trace,dir,group,groupCollapsed,groupEnd,time,timeEnd,profile,profileEnd,assert,count
* Internet Explorer 11: select,log,info,warn,error,debug,assert,time,timeEnd,timeStamp,group,groupCollapsed,groupEnd,trace,clear,dir,dirxml,count,countReset,cd
* Safari 6.2.4: debug,error,log,info,warn,clear,dir,dirxml,table,trace,assert,count,profile,profileEnd,time,timeEnd,timeStamp,group,groupCollapsed,groupEnd
* Opera 28.0.1750.48: debug,error,info,log,warn,dir,dirxml,table,trace,assert,count,markTimeline,profile,profileEnd,time,timeEnd,timeStamp,timeline,timelineEnd,group,groupCollapsed,groupEnd,clear
*/
(function() {
// Union of Chrome, Firefox, IE, Opera, and Safari console methods
var methods = ["assert", "cd", "clear", "count", "countReset",
"debug", "dir", "dirxml", "error", "exception", "group", "groupCollapsed",
"groupEnd", "info", "log", "markTimeline", "profile", "profileEnd",
"select", "table", "time", "timeEnd", "timeStamp", "timeline",
"timelineEnd", "trace", "warn"];
var length = methods.length;
var console = (window.console = window.console || {});
var method;
var noop = function() {};
while (length--) {
method = methods[length];
// define undefined methods as noops to prevent errors
if (!console[method])
console[method] = noop;
}
})();
The function closure wrapper is to scope the variables as to not define any variables. This guards against both undefined console and undefined console.debug (and other missing methods).
EDIT: I noticed that HTML5 Boilerplate uses similar code in its js/plugins.js file, if you're looking for a solution that will (probably) be kept up-to-date.
If you're running console.log() from a JS file, this undefined line should not be appended.
If you're running console.log() from the console itself, it makes sense. This is why: In the console you can type a name of a variable (for example try typing window) and it prints info about it. When you run any void function (like console.log) from the console, it also prints out info about the return value, undefined in this case.
I tested both cases on my Chrome (Mac ver 23.0.1271.101) and indeed I see the undefined line when I run it inside the console. This undefined also appears when I write this line in the console: var bla = "sdfdfs"
Although talkol´s answer is ok, I try to put it more straight:
JavaScript is designed as a dynamic language which means that the type (string, void, boolean …) of a function return value is not pre-defined. If a function does not use a return statement or an empty return statement with no value, JavaScript automatically returns undefined. That means that in JavaScript every function returns something, at least undefined.
So the function console.log() in Chrome console either uses no or an empty return statement, so that the return value of this function is undefined. This function return value gets also displayed in the Chrome console.
[If somebody know where to find the definition of the console.log() function in Google Chrome source code, please comment with the link, then we can even go further and look at the real code, would be nice.]
Sources:
- https://stackoverflow.com/a/20915524/1744768
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript