I've given some thoughts on declaring a variable called undefined and evaluating a truthy if-else expression with it. I found out that it is not possible in global scope. But in MDN I've found some interesting insight about the undefined datatype. I am directly quoting from MDN
undefined is a property of the global object; i.e., it is a variable
in global scope.
It doesn't say anything about local scope. That means i can create one in local scope. So, I move on to put this insight to test. I have created an object and assign a method to it
var person = {
method : function(){
var undefined = 2
if(undefined){
console.log("undefined works as a variable")
}
}
}
person.method()
And guess what! the if statement passes the test and the string inside the console.log() gets printed on the console.This might be a dangerous thing and of course a bad practice. Is there any way to prevent the declaration of a variable named after undefined keyword in javascript's local scope ? Thanks!
To work around accidental modification of undefined, you should not write this dangerous word in your code at all.
Since you only need read access to undefined, it is recommended to always use void 0 instead, which returns undefined.
var person = {
method: function() {
var undefined = 2
if(void 0) {
console.log("this should never be printed")
} else {
console.log("void 0 is always undefined, no matter what you do")
}
}
}
person.method()
How to work with void 0 and completely get rid of the word "undefined"?
// Turn
if(myVariable === undefined) { ... }
if(typeof myVariable === "undefined") { ... }
// into
if(myVariable === void 0) { ... }
// Turn
if((myVariable === undefined) || (myVariable === null)) { ... }
// into
if(myVariable == null) { ... }
// Turn
myObject.someKey = undefined
// into
myObject.someKey = void 0
Welcome to the wonderful world of JavaScript!
There is no way to prevent someone from doing this, but there is a way to ensure that undefined will mean undefined if you set up your functions as follows (not that you should really have to do this because it would be very bad practice for anyone to actually set up a variable named undefined). Essentially smaller scoped functions could hide a higher scoped undefined variable.
// This is just a way to get a variable called "undefined"
function wrapper(){
var undefined = 10;
console.log("wrapper says undefined is: " + undefined);
// This function declared a parameter called "undefined",
// but if the function gets called with no argument, then
// the value of this, more local, argument will truly be
// undefined. If arguments are needed, just add "undefined"
// to the end of the list.
function foo(undefined){
// Formal test to ensure that undefined is what we believe it to be:
if(typeof undefined === "undefined"){
console.log("foo says undefined is: " + undefined);
}
}
// When foo is called with no arguments passed in, the parameter
// "undefined" will take on a value of undefined within the scope
// of that function.
foo();
}
wrapper();
Now, that's a bit contrived as you're not going to set up all your functions with a "fake" argument, but you could test to see if undefined has been altered with:
function wrapper(){
var undefined = 10;
console.log(undefined);
function foo(){
if(typeof undefined === "undefined"){
// undefined has not been altered
} else {
// undefined has been altered, so reset it for this scope:
let undefined;
console.log(undefined);
}
}
foo();
}
wrapper();
In the end though, you could simply prevent this from affecting your functions by adding var undefined in your functions. Hoisting will make sure that this kicks in at the top of your function, no matter where you declare it.
I can't see any way to stop it, but yes, You can restrict it passing the yes inside If you can make the scope local using ES6.
You will find how scope if changed now and it's not the same thing.
var person = {
method : function(){
let undefined = 2
if(undefined){
console.log("undefined works as a variable")
}
}
}
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);
How do I check whether a variable name is "in use"? Meaning: how do I check if a variable name has already been used in a var varname = 'something' statement?
Normally, I would just check if typeof varname == 'undefined', which seems to work fine. The issue is when there is an element on the page with id="varname". Now, when I check typeof varname == 'undefined', i get false regardless, because varname is some HTML element.
varname is not "in use", but it is not undefined either.
<body id="test1"></body>
<script>
//if <body> has an id of test1, how do i check if test1 is undeclared?
console.log(typeof test1 == 'undefined'); // the <body> element causes this to be true
console.log(typeof test2 == 'undefined'); // outputs true as expected
</script>
Additionally, can you check for the corner case: var test1 = document.getElementById('test1') has been executed?
The only possible way to achieve what you need is through the evil eval(), as it is not possible to access local variables through their name as strings. (Globals are possible using window["variableNameAsString"].)
The solution snippet presented below has the following effect:
Returns true if varName was declared and initialized (even if with null) and is readable from the current scope. Otherwise returns false.
DEMO jsFiddle here.
Source:
function removeIdOfAllElementsWithId(id) {
var element, elementsFound = [];
while ((element = document.getElementById(id)) !== null) {
element.removeAttribute('id')
elementsFound.push(element);
}
return elementsFound;
}
function assignIdToElements(elements, id) {
for (var i = 0, n = elements.length; i < n; i++) { elements[i].id = id; }
}
var isDefinedEval = '(' +
function (isDefinedEvalVarname) {
var isDefinedEvalResult;
var isDefinedEvalElementsFound = removeIdOfAllElementsWithId(isDefinedEvalVarname);
try {
isDefinedEvalResult = eval('typeof '+isDefinedEvalVarname+' !== "undefined"');
} catch (e) {
isDefinedEvalResult = false;
}
assignIdToElements(isDefinedEvalElementsFound, isDefinedEvalVarname);
return isDefinedEvalResult;
}
+ ')';
Usage:
To test if a variable with name variableName is defined:
eval(isDefinedEval + '("' + 'variableName' + '")') === true
To check if it is not defined:
eval(isDefinedEval + '("' + 'variableName' + '")') === false
In the fiddle you'll find lots of unit tests demonstrating and verifying the behavior.
Tests:
Several tests are included in the fiddle;
This snippet was tested in IE7, IE8 and IE9 plus latests Chrome and Firefox.
Explanation:
The function must be used through eval() because it needs to have access to the variables locally declared.
To access such variables, a function must be declared in the same scope. That's what eval() does there: It declares the function in the local scope and then calls it with varName as argument.
Aside that, the function basically:
- Removes the ID attribute of every element that has an ID === varName;
- Checks if the variable is undefined;
- And reassign the ID of those elements it removed the attribute.
Note: this answer was heavily edited, some coments may not be still appliable.
Not sure if this what you are looking for.
if(typeof test1 == "undefined" && document.getElementById("test1") == null) {
//There is no element with an id="test1" and a variable test1
}
In a context other than the global context in some browsers, it is impossible to reliably determine if a variable has been defined (either by being declared or otherwise initialised) or not other than using try..catch.
Therefore it's not a good strategy to need to do that.
In a global context, in non–IE browsers, you can do something like:
var global = this;
if (!global.hasOwnProperty('foo')) {
// there is no global foo
}
but IE doesn't implement hasOwnProperty on the global object. Note that DOM element names and IDs do not overwrite the value of declared global variables.
But anyway, all this is useless since you may well have:
var foo = document.getElementById('foo');
What now?
So I've been doing this for as long as I can remember, but I'm curious if this is really what I should be doing. You write a function that takes a parameter, so you anticipate it to have a value, but if it doesn't, you have a good reason to default it, to say zero. What I currently do is write a helper function:
function foo() { return foo(0); };
function foo(bar) { ... };
I just ran across an instance where I did this and I looked at it oddly for a few seconds before understanding my logic behind it. I come from php where it's trivial:
function foo(bar=0) { ... }
Is there a javascript alternative that I'm not aware of?
You can't have overloaded functions in JavaScript. Instead, use object based initialization, or check for the values and assign a default if none supplied.
In your example, the second function foo(bar) will replace the first one.
Here's a function using object initialization.
function foo(config) {
extend(this, config);
}
where extend is a function that merges the config object with the current object. It is similar to the $.extend method in jQuery, or $extend method of MooTools.
Invoke the function and pass it named key value pairs
foo({ bar: 0 });
The other way to initialize is to look at the supplied values, and assign a default if the value is not given
function foo(bar) {
bar = bar || 0;
}
This works as long as bar is not a falsy value. So foo(false) or foo("") will still initialize bar to 0. For such cases, do an explicit check.
function foo(bar) {
bar = (typeof bar == 'undefined' ? 0 : bar);
}
In JavaScript, the argument will be undefined if the user didn't pass it in. You can use the || operator to set the value of the argument if it's undefined:
function foo(bar) {
bar = bar || 0;
...
}
The simplest way I know of is test for a value and then set it to a default value if no value is found. I have not come across a catch all one liner yet, this is the best i have got.
If expecting a string value use this. Default will trigger on these values: [ undefined, null, "" ]
function foo(str) {
str = !!str ? str : 'bar';
...
}
If expecting a number or Boolean value. This allows 0 and false as values. Default will trigger on [ undefined, null, {}, functions ]
Handy for making values arguments that only accept primitive values like number, boolean and string
function foo(val) {
val= !!val == val || val*1 ? val : 10;
...
}
If you're looking to test for objects such as {}, There is documentation on doing this but it isn't so simple.
Hopefully this answers a bit clearer for someone - I ended up using the ol' check for undefined if(typeof functionparameter !== 'undefined') as per:
$.fn.extend({
doThing: function(stringparameter = 'FooBar!', functionparameter){
console.log('Here is your string '+stringparameter);
// Run it if it's been passed through:
if(typeof functionparameter !== 'undefined') functionparameter();
});