使用间接调用eval
可以使用间接调用来访问全局const
和定义。即生成逗号分隔表达式的结果或首先将其分配给变量。如果语法访问不是直接访问内置函数,则它是间接访问,并且间接访问在全局范围内执行。let
eval
eval
eval
您也可以let
通过构建脚本来设置全局变量来执行设置操作。
"use strict";
let myVar = "global variable myVar";
console.log( myVar);
(function myLibrary() {
const myVar = "local variable myVar";
const indirectEval = eval;
var varName = "myVar";
console.log( eval(varName)); // direct call uses local scope
console.log( indirectEval(varName)); // indirect call uses global scope
var result = "\"updated global variable even though shadowed\"";
var js = varName + '=' + result;
indirectEval(js);
// but trying to define a new let variable doesn't attach to global scope
var js2 ='let letVar2 = "let variable two"';
indirectEval( js2);
})();
console.log( myVar)
console.log( "letVar2: " + typeof letVar2);
你不能做的是使用对 eval 的间接调用将一个let
or变量添加到全局范围:它们是块级声明,并且代码评估被认为是一个块 - 所以当(间接调用)返回时,声明将被丢弃。const
eval
eval
PS。这是一个技术答案。是的,我之前听说过“eval 是邪恶的”一到三遍。
对于仅使用硬编码变量名称字符串的读取访问(以防止代码插入),您可以使用以下模式:
(0,eval)("identifierString");
例如:
var x = 3;
const y = 7;
let z = 21;
{
const y = "shadow"
let z = 42;
console.log('x = ' + (0,eval)('x')); //x = 3
console.log('y = ' + (0,eval)('y')); //y = 7
console.log('z = ' + (0,eval)('z')); //z = 21
}
间接与直接调用eval
直接调用eval
只获取未在调用的函数范围内隐藏的全局变量的值。这可能会限制变量名称的选择,或者在库中可以从哪里进行调用。
间接调用在全局范围内执行,并且可以获取全局变量的值,而与库中的名称阴影无关。
从源文本创建一个新Function
对象并调用它,可以作为eval
在网页中使用间接调用的替代方法。然而,差异主要是语义上的,而不是一个比另一个更好。
问题
如果全局变量名称(var
、或标识符)来自用户输入,则确实应该检查其有效性(let
不是那么容易)或至少在 try/catch 块中访问以捕获使用未声明的标识符或使用之前的名称声明初始化。const
class
就我个人而言,我建议通常寻找替代使用全局变量名称字符串的方法。myLibrary.data
想到在库上提供静态名称空间对象(例如)并处理作为对象属性名称的字符串值,或者在库调用中包括选项对象参数。