我正在尝试实现类似于angular.isDefined(...)
但是允许检查变量及其属性,所以我写了这个概念证明:
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');
我知道typeof
允许使用未声明的标识符,并且似乎可以在eval()
内正常工作:
console.log(typeof someVariableWhichDoesNotExists)
console.log(eval('typeof someVariableWhichDoesNotExists'));
但是在我的代码中,当eval()
处理它时,它失败了。我想念什么?
PS:我已经读过Why does typeof only sometimes throw ReferenceError?,但我认为情况不尽相同,这里我不是在检查表达式,而只是在检查标识符。
答案 0 :(得分:10)
这实际上与eval()
没有关系。您的错误是由定义let obj
引起的,但是在定义之前尝试使用它。 here描述了此异常:
但是,通过添加块范围的let和const,在声明它们之前在块中使用let和const变量上的typeof(或在类上使用typeof)会抛出ReferenceError。从块的开始一直到处理初始化为止,块范围的变量都处于“临时死区”,在此期间,如果被访问,它将引发错误
如果没有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 = {}
如果您删除let obj={};
声明或使用var obj = {}
,您的错误就会消失。