I was trying to implement a function similar to angular.isDefined(...)
but allowing to check variables and their properties, so I wrote this proof of concept:
function check(s) {
let parts = s.split('\.');
let partial = '';
return parts.every(p => {
partial += (partial ? '.': '') + p;
let expr = `typeof ${partial}`;
console.log('Evaluating', expr);
return eval(expr) !== 'undefined';
});
}
check('obj');
let obj={};
check('obj');
obj.a=1;
check('obj.a');
I know that typeof
allows a non declared identifier, and it seems to work properly within eval()
:
console.log(typeof someVariableWhichDoesNotExists)
console.log(eval('typeof someVariableWhichDoesNotExists'));
But in my code fails when it is processed by eval()
. What am I missing?
PS: I've read Why does typeof only sometimes throw ReferenceError? but I think it is not the same scenario, I am not checking an expression here, but just a identifier.
This actually has nothing to do with eval()
. Your error is caused by defining let obj
but trying to use it before it is defined. This exception is described here:
But with the addition of block-scoped let and const, using typeof on let and const variables (or using typeof on a class) in a block before they are declared will throw a ReferenceError. Block scoped variables are in a "temporal dead zone" from the start of the block until the initialization is processed, during which, it will throw an error if accessed
You can cause this error easily without eval()
:
// undefined no problem because obj was not declared
console.log(typeof obj)
// undefined but variable declared with let
// but not defined before using it results in an error
console.log(typeof otherobj)
let otherobj = {}
Your error goes away if you remove the let obj={};
declaration or use var obj = {}
.