故障评估';正在初始化函数定义(…在JavaScript中)
我试图通过评估用户提供的字符串来构建一个简单的REPL。除了像“function f(){…}”这样的输入之外,它似乎在大部分情况下都有效,这对以后的evals中哪些函数是可见的没有影响。在玩了一会儿之后,我只能得出结论,我根本不懂eval。下面是一个演示一些神秘行为的小片段:故障评估';正在初始化函数定义(…在JavaScript中),javascript,function,eval,Javascript,Function,Eval,我试图通过评估用户提供的字符串来构建一个简单的REPL。除了像“function f(){…}”这样的输入之外,它似乎在大部分情况下都有效,这对以后的evals中哪些函数是可见的没有影响。在玩了一会儿之后,我只能得出结论,我根本不懂eval。下面是一个演示一些神秘行为的小片段: var xeval = eval; function silly() {} eval("function good() {}"); function baffleMe() { eval("alsoGood
var xeval = eval;
function silly() {}
eval("function good() {}");
function baffleMe() {
eval("alsoGood = function() {}");
eval("function notSoGood() {}");
xeval("function hope() {}");
xeval("function crushedHope() { silly(); }");
}
baffleMe();
good(); // Okay.
alsoGood(); // Okay.
notSoGood(); // ReferenceError: notSoGood is not defined
hope(); // Why does this even work?
crushedHope(); // ReferenceError: silly is not defined
有人能解释一下这些结果吗?(可在最新的Chrome和Firefox中复制)
[编辑]
为了澄清这一点,最后一个调用只有在Javascript控制台或类似JSFIDLE的工具中执行代码时才会失败,但在嵌入脚本标记时不会失败。关于已接受答案的评论包含对此的解释。我将尝试解释:
在全球范围内对货物进行评估:
good(); // Okay.
alsoGood(); // Okay.
notSoGood(); // ReferenceError: notSoGood is not defined
hope(); // Why does this even work?
Alsogood没有var定义,因此在全局范围内定义:
good(); // Okay.
alsoGood(); // Okay.
notSoGood(); // ReferenceError: notSoGood is not defined
hope(); // Why does this even work?
NotSoGood在功能范围内定义,因此不存在于全局范围内:
good(); // Okay.
alsoGood(); // Okay.
notSoGood(); // ReferenceError: notSoGood is not defined
hope(); // Why does this even work?
Hope在全球范围内通过eval的闭包引用进行评估,因此在全球范围内进行评估:
good(); // Okay.
alsoGood(); // Okay.
notSoGood(); // ReferenceError: notSoGood is not defined
hope(); // Why does this even work?
CrushedHope与hope相同,但在本例中应定义为愚蠢:
crushedHope(); // ReferenceError: silly is not defined
正如下面的评论中所提到的,当使用JSFIDLE和代码用
窗口包装时,问题中没有定义SPILL。onload
这是ECMAScript 5的一个特性。致:
如果间接使用eval函数,则从ECMAScript 5开始,通过eval以外的引用调用eval函数,它在全局范围而不是局部范围内工作;这意味着,例如,函数声明创建了全局函数,并且正在求值的代码不能访问调用它的范围内的局部变量
因此,直接调用eval()
将在本地范围内创建函数。(使用a=something
方法会自动创建一个全局变量。)但当您通过xeval()
间接调用它时,它会得到全局求值
未定义的
愚蠢的的最终结果取决于您正在评估的范围。如果您在控制台中,它的作用域似乎不同。如果您创建一个测试HTML页面,它可以正常工作。请参阅window.eval
(global.eval
在节点中)和eval
之间的区别:如果您要进行REPL,您应该将字符串evals放入try catch
语句中,如果错误消息是输入意外结束
,然后提示输入更多代码,直到eval
生效,或者返回不同的错误。@user3026691crushedhoope
不会产生我在Chrome和Firefox控制台中测试时所描述的错误。您在哪里看到这个错误?@user3026691啊,我看到了问题:如果您的代码不是全局的(例如,包装在(function(){…})中)()
iLife,那么silly
不是全局的。但是,crushedhephope
是全局的,所以它在iLife中看不到本地定义的silly
函数。它在JSFIDLE和Javascript控制台中都可以看到…0_o@user3026691您需要将您的小提琴“加载类型”设置从“onLoad”更改为“No wrap”。在加载
事件侦听器函数中定义愚蠢的
函数会使全局作用域无法访问该函数