在JavaScript中使用eval()函数时如何捕获全局常量变量更改错误

zcm*_*rld 8 javascript

我试着检查es6中的"变量"是否是常量:

const a = 1;
function test() {
  try {
    a = 2;// throws an error
  } catch (error) {
    console.log(error)
  }
}
test();
Run Code Online (Sandbox Code Playgroud)

但是当我使用eval()函数时,它不会抛出错误.

const a = 1;
function test() {
  try {
    eval("a = 2;")// not throws an error
  } catch (error) {
    console.log(error)
  }
}
test();
Run Code Online (Sandbox Code Playgroud)

并且我使常量局部,函数eval确实抛出了预期的错误.

function test() {
  try {
    const a = 1;
    eval("a = 2;")//throws an error
  } catch (error) {
    console.log(error)
  }
}
test();
Run Code Online (Sandbox Code Playgroud)

当我使用函数eval()导致它不会像预期的那样抛出错误.functoin eval()在这里做了什么?我在Node v6.2.2中运行它

const a = 1;

function test() {
  try {
    eval("");
    a = 2; // will not throw an error
  } catch (e) {
    console.log(e)
  }
}
test();
Run Code Online (Sandbox Code Playgroud)

更有趣的是,我用if(false)包含eval(),它也不会抛出错误.

const a = 1;

function test() {
  try {
    if (false) {
      eval(""); 
    }
    a = 2; // will not throw an error
  } catch (e) {
    console.log(e)
  }
}
test();
Run Code Online (Sandbox Code Playgroud)

谁能告诉我原因?

这是JavaScript中的错误吗?

如何捕获全局常量变量更改错误?

T.J*_*der 4

事实上,eval("a = 2;")您的代码中不会抛出TypeError看起来像 V8(Chrome 中的 JavaScript 引擎)中的错误。

const通过规范操作 CreateImmutableBinding创建严格绑定(请参阅GlobalDeclarationInstantiation的步骤 16.bi1 )。

当分配给不可变绑定 ( a = 2) 时,如果TypeError满足 1. 代码处于严格模式,或者 2. 绑定是严格绑定,则将抛出aSetMutableBinding

因此,在不使用 的代码中eval,您正在松散模式下运行,但TypeError无论如何它都会抛出 a ,因为绑定是严格的。但当你这样做时,V8 似乎并没有检查绑定是否严格eval("a = 2;")。(SpiderMonkey [Firefox] 会这样做,并抛出TypeError; ,就像 IE11 中的 JScript 一样。我没有方便的 Edge 来检查 Chakra。)

您可以通过将代码设置为evalstrict 来使 V8 抛出错误:

const a = 1;
function test() {
  try {
    eval("'use strict'; a = 2;");
  }
  catch (error) {
    console.log(error);
  }
}
test();
Run Code Online (Sandbox Code Playgroud)

  • @robertklep:这部分并不奇怪(如果是 2,那会很奇怪!),规范中定义了几个非严格只读绑定,这就是它们在松散模式下的行为方式(写入会被默默忽略) 。例如,命名函数表达式(而不是声明)中的函数名称是函数内的只读、非严格绑定,因此 `(function foo() { foo = 42; console.log(typeof foo) ; })()` 以松散模式输出 `"function"`(不抛出异常)。 (2认同)