I happened upon something strange (at least to me), and maybe someone can elaborate on this for me:
const a = undefined;
const c = {};
/** this works correctly **/
console.log(a === undefined);
/** this does not throw an exception **/
console.log(c.someProperty === undefined);
/** this throws an exception, why? **/
console.log(b === undefined);
Just is in the example above, why is it, that if I want to check for an objects property, with === undefined which was not defined everything is okay, but as soon as I try to check for a top-level variable for being defined, I am getting an error?
Here's a fiddle.
The ECMAScript Language Specification states that accessing a nonexistent variable throws a ReferenceError (see GetValue) while accessing a nonexistent property results in undefined (see OrdinaryGet).
To check if a global variable is defined, you can use typeof, which does not throw.
console.log(typeof b === 'undefined');
Top-level variables declared with var also exist on the window object, so you can use a property access too.
console.log(window.b === undefined);
The thing is that b is not undefined, it is not even declared.You cannot call a variable that is not declared, be you can with one that is declared but undefined.
const a = undefined;
const b
const c = {};
console.log(a === undefined) //true
console.log(b === undefined) //true
console.log(c.someProperty === undefined) //true
console.log(typeof d === 'undefined') //true, it does not exist
try{
console.log(d)
} catch (e) {
console.log('error!')
} //error!
Related
I know that to find if a variable is undeclared in javascript, I can use if (typeof variable === 'undefined'). If I declare a variable as undefined (var variable = undefined), the if statement still returns true. Is it possible, in JavaScript, to find the difference between undeclared variables and variables with a value of undefined? I know that they are similar, but doing const variable = undefined and then variable = "something else" will throw an error, so they must be different.
const variable = undefined
if (typeof variable === 'undefined') {
console.log('"variable" is undefined')
}
if (typeof undeclaredVariable === 'undefined') {
console.log('"undeclaredVariable" is undefined')
}
I wouldn't like to use a try catch block because I want to be able to assign another constant based on this. I would like a solution like this: const isVariableDeclared = variable === undeclared, except undeclared does not exist in javascript. I know I can use let with a try catch block but am looking for something more elegant.
At least in the time of writing... No, it does not seem that you can do something like this:
var a = undeclared(var) ? 'undeclared' : 'undefined'
The reason is that you cannot pass an undeclared variable to a function; It raises an error, even in non-strict mode.
The best we can do, is this:
var barIsDeclared = true;
try { bar; }
catch (e) {
if (e.name == "ReferenceError") {
barIsDeclared = false;
}
}
console.log(barIsDeclared);
Why?
Undefined: It occurs when a variable has been declared but has not
been assigned with any value. Undefined is not a keyword.
Undeclared: It occurs when we try to access any variable that is not
initialized or declared earlier using var or const keyword. If we use
‘typeof’ operator to get the value of an undeclared variable, we will
face the runtime error with return value as “undefined”. The scope of
the undeclared variables is always global.
For example:
Undefined:
var a;
undefined
console.log(a) // Success!
Undeclared:
console.log(myVariable) // ReferenceError: myVariable is not defined
When we try to log an undeclared variable, it raises an error. Trying to log an undefined variable does not. We make a try catch to check for just that.
'use strict'
Worth mentioning that adding 'use strict' in your code verifies that no undeclared variable is present, and raises an error if one is present.
function define() {
//'use strict' verifies that no undeclared variable is present in our code
'use strict';
x = "Defined";
}
define();
ReferenceError: x is not defined
Further reading:
Checking if a variable exists in javascript
What are undeclared and undefined variables in JavaScript?
JS Interview Question: What’s the difference between a variable that is: null, undefined or undeclared?
JavaScript check if variable exists (is defined/initialized)
Strict mode
As others already did point to, the OP might want to distinguish between declared but undefined references and undeclared reference names ...
let declaredButUnassignedAndStrictlyEqualToUndefinedValue;
const declaredAndHavingAssignedTheUndefinedValue = undefined;
// There is no way of telling the above two (un/)assignements appart.
console.log(
'(declaredButUnassignedAndStrictlyEqualToUndefinedValue === declaredAndHavingAssignedTheUndefinedValue) ?',
(declaredButUnassignedAndStrictlyEqualToUndefinedValue === declaredAndHavingAssignedTheUndefinedValue)
);
// the `typeof` operator is of no help
// if it comes to distinguish between
// declared but undefined references
// and undeclared reference names ...
console.log(
'typeof notDeclaredWithinScope :', typeof notDeclaredWithinScope
);
// ... just a try catch can do that.
try {
notDeclaredWithinScope;
} catch (err) {
// console.log(err.message);
console.log('`notDeclaredWithinScope` does not exist within this scope.')
}
.as-console-wrapper { min-height: 100%!important; top: 0; }
Thanks for all of the help! I've pieced together a simple solution that fits my needs from all of the answers if anyone wants it. The only drawback is that variable names must be passed as strings. It uses a try catch block but I can still use it for my original use case (assign a constant based on it).
function declared(variable) {
let declared = true;
try {
eval(variable);
} catch (e) {
if (e.name === "ReferenceError") {
declared = false;
}
}
return declared;
}
let declaredVar;
console.log(declared("declaredVar")); // true
console.log(declared("undeclaredVar")); // false
function typeOf(variable) {
return eval("typeof " + variable) === "undefined"
? declared(variable)
? "undefined"
: "undeclared"
: eval("typeof " + variable);
}
const stringVar = "string";
const undefinedVar = undefined;
console.log(typeOf("stringVar")); // string
console.log(typeOf("undefinedVar")); // undefined
console.log(typeOf("undeclaredVar")); // undeclared
I understood what your saying. There is no defined way to get the exact answer but there is a way to find whether it is defined or not. It is possible only if it referenced somewhere.
Eg:
// Lets think x is not defined
x.substring(1);
Output:
ReferenceError: "x" is not defined
So if you use try catch block method, with the help of catch error message you can identify whether it is defined or not!
I have the function:
isset = function(obj){
alert(obj !== undefined);
}
Then when I do isset(defined_variable) where defined_variable has been declared, the alert box shows true but when I do isset(undefined_variable) where undefined_variable has not been declared, the alert box does not show at all, while I expected the alert box to show false. What am I doing wrong? I have tried using typeof but the results are the same.
That's because there's a difference between undefined and undeclared.
var foo; // foo is undefined.
// bar is undeclared.
console.log(foo === undefined); // true
try {
console.log(bar === undefined);
} catch (e) {
console.error('I had an error!'); // gets invoked.
}
foo = 'something';
console.log(foo === undefined); // false
but when I do isset(undefined_variable) where udefined_variable has
not been declared, the alert box does not show at all, while I
expected the alert box to show false
because it throws an error in your console (check your console) that this variable that you are comparing is not defined.
Uncaught ReferenceError: 'c' is not defined
i tried with isset( c ) and c was not declared first
When you dereference an undeclared variable (meaning you try to use a symbol that was never wrote before), you get a Reference error.
There are several ways to deal with this, but you can't determine what are local variables in javascript. Thus, your problem can be solved dynamically only for global variables, or a given scope object.
No functions could handle local scope dynamically.
You can prefix it with window if you are in a browser context (for more context see this SO answer about global object in javascript)
This would not modify your isset function code:
isset(window.undefined_variable)
There would be another way, which would need that isset function changes, but uses the same principle (still in browser context):
isset('undefined_variable_name_wrawppped_in_a_string')
function isset(name) {
return name in window;
}
We can't really use typeof in isset, it's sad because it would be convenient since it doesn't throw a Reference Error when the variable was never declared. We could still use a form of eval to do it, but since I don't want us to go there, I won't implement it.
But now, what if you want to check several nested properties?
function isset (memoryPath, root) {
var nodeNames = memoryPath.split('.');
var expectedDepthReached = nodeNames.length;
var depthReached = 0;
var nodeName;
var node = root;
// we are gonna read it from left to right
// using Array.prototype.pop()
// reversing it will alow us to do so
nodeNames.reverse();
do {
nodeName = nodeNames.pop();
node = node[nodeName];
if (node) {
depthReached++;
}
} while (node);
return depthReached === expectedDepthReached;
}
And an exemple:
window.myGlobals = {
path: {
to: {
a: {
variable: true
}
}
}
};
isset('myGlobals.path.to.a.variable', window), // true
isset('myGlobals.path.foo', window) // false
I am writing a script that deals with a variable gameRegion like so:
//In the main of the script
var variable= new work();
variable.onCrash(crashHandler,{xPos:650,yPos:300});
// In function work()
var gameRegion;
var onCrashCallback;
this.onCrash = function(crashCallback,fieldSize) {
gameRegion = fieldSize;
onCrashCallback = crashCallback;
};
crashHandler(){
//unimportant
}
this.atBottom = function(ypos) {
if(ypos>gameRegion.yPos) //line with the problem
return true;
return false;
};
I am getting the console error: TypeError: 'undefined' is not an object (evaluating 'gameRegion.yPos'). Presumably that means I am not properly defining gameRegion or its variable yPos. I've been looking at this code for a while now and I can't seem to find what the problem is.
Hopefully you'll see something that I don't, but if I'm not including necessary code for context, please tell me. Thanks for any help in advance.
You have to handle 'undefined'. Which can be done in these ways:
typeof(foo) == 'undefined'
typeof foo !== 'undefined'
window.foo !== undefined
'foo' in window
The first three should be equivalent (as long as foo isn't shadowed by a local variable), whereas the last one will return true if the global varible is defined, but not initialized (or explicitly set to undefined).
You can use typeof like so -
return (typeof (gameRegion) !== "undefined" &&
typeof(gameRegion.yPos) !== "undefined" &&
ypos > gameRegion.yPos);
Where am I doing wrong?
I would wait "Class" as a result of this code but it doesn't:
This is from object function:
Tyepof doesnt work like that, it only returns built in types. You could try:
this.constructor.name==="Class";
It will check all the way up the prototype chain to see if this or any prototype of this is Class. So if OtherType.prototype=Object.create(Class); then it'll be true for any OtherType instances. Does NOT work in < IE9
or
this instanceof Class
But that will not check the entire prototype chain.
Here is a list of return values typeof can return
Here is an answer about getting the type of a variable that has much more detail and shows many ways it can break.
Because JavaScript knows only the following types :
Undefined - "undefined"
Null - "object"
Boolean - "boolean"
Number - "number"
String - "string"
Host object (provided by the JS environment) - Implementation-dependent
Function object (implements [[Call]] in ECMA-262 terms) - "function"
E4X XML object - "xml"
E4X XMLList object - "xml"
Any other object - "object"
You can find more here
Read this thread to find how you can get the object name
object.constructor.name will return constructor's name. Here is an example:
function SomeClass() {
/* code */
}
var obj = new SomeClass();
// obj.constructor.name == "SomeClass"
Be aware that you need to use named functions, if you assign anonymous functions to variables, it will be an empty string...
var SomeClass = function () {
/* code */
};
var obj = new SomeClass();
// obj.constructor.name == ""
But you can use both, then the named function's name will be returned
var SomeClassCtor = function SomeClass() {
/* code */
};
var obj = new SomeClassCtor();
// obj.constructor.name == "SomeClass"
You may try this as well
function getType(obj){
if (obj === undefined) { return 'undefined'; }
if (obj === null) { return 'null'; }
return obj.constructor.name || Object.prototype.toString.call(obj).split(' ').pop().split(']').shift().toLowerCase();
}
An Example Here.
function MyClass(){}
console.log(getType(new MyClass)); // MyClass
console.log(getType([])); // Array
console.log(getType({})); // Object
console.log(getType(new Array)); // Array
console.log(getType(new Object)); // Object
console.log(getType(new Date)); // Date
console.log(getType(new Error)); // Error
I need to be able to check if a variable exists (if if it doesn't assign it to {}) without throwing an error in javascript. When I try this code
if (a) {}
it throws uncaughtReferenceError
What I really want to do is something like this without throwing an error:
a = a || {}
or maybe it looks like this
if (a) { a = {} }
if (typeof a === 'undefined'){
// variable is not available and you can write a = {}
}
but a = a || {} is shortly
If a is a global, you can use the global object to avoid the error. In browsers, that object is window:
window.a = window.a || {};
Or, as Ozerich suggested, you can use typeof, which won't throw reference errors:
if (typeof a === 'undefined') {
a = {};
}
a = a || {}
simply won't work, because a is not defined. But you can use typeof to check if it exists or not.
a = (typeof(a) === 'undefined' ? {} : a);