javascript - window[name] 相当于动态访问 const 和 let 声明

标签 javascript browser constants variable-declaration window-object

闭包外部的旧式 JavaScript var 声明是全局的(顶级范围),可以在浏览器中从 window 对象访问。例如,可以使用 window['x'] 访问声明 var x = 3;

如何在给定声明名称(字符串)的情况下类似地访问 constlet 声明?

var x = 3;
const y = 7;
let z = 21;

console.log('x = ' + window['x']);  //x = 3
console.log('y = ' + window['y']);  //y = undefined
console.log('z = ' + window['z']);  //z = undefined

对于上面的示例,如何获取“y”和“z”的值 721 而不是 undefined

摆弄代码:
https://jsfiddle.net/g78ah6we/

编辑(为清晰起见添加注释):
1. 虽然不典型,但也有一些用例,例如 library 中的用例。 ,有必要仅根据声明的名称来访问声明。
2. 只需要读取权限(不会修改任何声明)。
3. 提到 window 对象只是为了展示旧的方式,但这个问题实际上并不是关于使用 window 对象(或 global对象)。

最佳答案

使用间接调用eval

可以使用对eval的间接调用来访问全局constlet定义。也就是说,使 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 的间接调用将 letconst 变量添加到全局范围:它们是 block 级声明,并且代码 eval 评估被视为一个 block - 因此当(间接调用)eval 返回时,声明将被丢弃。

PS。这是一个技术性的答案。是的,我以前听说过“评估是邪恶的”,一三次。


对于仅使用硬编码变量名称字符串的读取访问(以防止代码插入),您可以使用以下模式:

 (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 的替代方法。然而,差异很大程度上是语义上的,而不是一个比另一个更好。

问题

如果全局变量名称(varletconstclass 标识符)来自用户输入确实应该检查它的有效性( not all that easy )或至少在 try/catch block 中访问它,以在初始化之前捕获未声明的标识符的使用或名称声明的使用。

我个人建议寻找一般使用全局变量名称字符串的替代方案。在库上提供静态 namespace 对象(例如 myLibrary.data)并处理作为对象属性名称的字符串值,或者在库调用中包含选项对象参数。

关于javascript - window[name] 相当于动态访问 const 和 let 声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50111200/

相关文章:

javascript - 查找并替换字符 jquery 之前的所有内容

javascript - 需要JS正则表达式来表示以下字符串

javascript - 为什么我的 ng-class 即使在 false 时也会显示

javascript - 使用 JavaScript 检测 HTML5

css - Masonry 博客在不同浏览器中的布局问题

c - 将常量添加到数组

javascript - 如何在 Qualtrics 中编写 JavaScript 以自动跨项目前进?

http - Web 浏览器并行下载与流水线

php - 如何在具有非固定宽度的正则表达式中模拟lookbehind

GCC 不同部分中的常量指针