在JavaScript
中严格模式到底限制了eval
什么?
背景:
在研究《JavaScript权威指南》这本书的时候,在eval()的那一章节中对一句话的理解模模糊糊的,对应的段落如下所示:严格模式下,被求值的代码可以查询和设置局部变量,但是不能 在局部作用域中定义新变量或函数;
下面便好好的进行研究:
eval()
函数它会使用调用它的代码的变量的环境,也就是说,他会像本地一样查找变量的值、定义新变量和函数。
在看到这句话的时候,我以为,所有的定义变量的方式,都会将新定义的变量的作用域设置为当前调用的环境,所以,也就存在上述的那段话一直不明白的原因。下面看我之前犯错误的时候的实验的代码;
1、错误的研究代码:
此时的测试的环境是在
node
中;
> function afun(){let name = "afun function ";eval("let name_1 = 'Eval function inner '");return name}
undefined
> afun()
'afun function '
> function afun(){let name = "afun function ";eval("let name_1 = 'Eval function inner '");return name_1}
undefined
> afun()
Uncaught ReferenceError: name_1 is not defined
at afun (REPL3:1:89)
>> afun()
'afun function '
> function afun(){let name = "afun function ";eval("name = 'Eval function inner '");return name}
undefined
> afun()
'Eval function inner '
>
我们发现,我们在eval()
中定义的这个变量只拥有块作用域。其实在这里已经能够发现问题所在了。因为自此ES6
之后引入的let
和const
都是属于拥有块作用域的。在这里,使用它们定义的变量无法先变量的值上升的调用eval()
的环境中,而是在这个块作用域中的一个环境中。
2、问题的发现:
在反复的阅读了这一篇的文章之后,发现如下的一段话:
如果这个函数调用了eval("var y = 3;"),则会声明一个新局部变量y。 另外,如果被求值的字符串使用了let 或 const,则声明的变量或 常量会被限制在求值的局部作用域内,不会定义到调用环境中。
看到上述的这段话,好家伙,我悟了。
且看如下的实验:
【实验一】:检测上述这段话中,条件:在函数中调用 的必要性
> eval('var d = 100;let b = 300; const c = 400;');
undefined
> d
100
> b
Uncaught ReferenceError: b is not defined
> c
Uncaught ReferenceError: c is not defined
>
上述的这段代码是在全局变量下的操作;我们发现,只用使用var
定义的变量才会将对应的作用域放在调用eval()
的环境中。
下面,来进行新的测试:
> function testStrict(){eval("'use strict';var a = 100;");console.log("a: " + a);}
undefined
> testStrict()
Uncaught ReferenceError: a is not defined
at testStrict (REPL4:1:77)
> function testStrict(){eval("var a = 100;");console.log("a: " + a);}
undefined
> testStrict()
a: 100
undefined
>
如上述的代码所示,'use strict'
限制的就是 eval()
在执行的字符串代码中 var
声明的变量的作用域提升到该操作调用的环境中这个情形;
3、总结:
果然,读书不可以偏概全,尤其是在阅读一些非常厚的经典书籍的时候,需要有耐性将其慢慢梳理,联系每章节之间的联系。