window [name]等效于动态访问const和let声明 [英] window[name] equivalent to dynamically access const and let declarations

查看:111
本文介绍了window [name]等效于动态访问const和let声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The old style JavaScript var declaration outside of a closure is global (top-level scope) and can be accessed in a browser from the window object. For example, the declaration var x = 3; can be accessed with window['x'].

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

How do you similarly access a const or let declaration given the name (string) of the declaration?

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"而不是undefined的值721?

For the above example, how do you get the values 7 and 21 for "y" and "z" instead of undefined?

在代码中加注:
https://jsfiddle.net/g78ah6we/

Fiddle with the code:
https://jsfiddle.net/g78ah6we/

编辑(为清楚起见添加了注释):
1.虽然不是很典型,但是有一些用例,例如在中,必须仅根据声明的名称访问声明.
2.仅需要读访问权限(任何声明都不会被修改).
3.提到window对象只是为了显示旧方法,但是实际上,这个问题与使用window对象(或global对象)无关.

Edits (notes added for clarity):
1. While not typical, there are use cases, such as from within a library, that it's necessary to access a declaration based only on the name of the declaration.
2. Only read access is needed (none of the declarations will be modified).
3. The window object is mentioned just to show the old way, but this question is not actually about using the window object (or the global object).

推荐答案

使用对eval

的间接调用

可以通过间接调用eval来访问全局constlet定义.也就是说,将eval作为逗号分隔表达式的结果,或者首先将其分配给变量.如果语法访问不是直接访问内置的eval函数,则它是间接访问,并且间接访问在全局范围内执行.

Using indirect calls to eval

Accessing global const and let definitions can be done using an indirect call to eval. That is make eval the result of a comma separated expression or assign it to a variable first. If the syntactic access is not directly to the built-in eval function it's an indirect access, and indirect access executes in global scope.

您还可以通过构建脚本来设置全局let变量来执行设置操作.

You can also set global let variables by building script to perform the setting operation.

"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变量添加到全局范围:它们是块级声明,而eval评估的代码被认为是一个块-因此声明(间接调用)eval返回时将被丢弃.

What you can't do is add a let or const variable to global scope using an indirect call to eval: they are block level declarations and the code eval evaluates is considered a block - so the declarations are discarded when (indirect call to ) eval returns.

PS.这是一个技术答案.是的,我听说过评估是邪恶的"一两次.


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

PS. This is a technical answer. And yes, I have heard that "eval is evil" before, one or three times.


For read access only using hard-coded variable name strings (to prevent code insertion) you could use the pattern:

 (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只会获取尚未在调用的函数范围内隐藏的全局变量的值.这可能会限制在库中选择变量名或从何处进行调用.

A direct call to eval only obtains the values of global variables that have not been shadowed in function scope of the call. This may restrict choice of variable names, or where the call can be made from, within the library.

间接调用在全局范围内执行,并且可以获取全局变量的值,而与库中的名称屏蔽无关.

An indirect call executes in global scope and can obtain the value of global variables irrespective of name shadowing within the library.

从源文本创建一个新的Function对象并对其进行调用,可以替代在网页中使用对eval的间接调用.但是,差异主要是语义上的,而不是一个比另一个更好.

Creating a new Function object from source text, and calling it, may provide be an alternative to using an indirect call to eval in a web page. However the difference is largely semantic rather than one being better than the other.

如果全局变量名称(varletconstclass标识符)来自用户输入,则实际上应该检查其有效性(

If the global variable name (var, let, const or class identifier) comes from user input it really should be checked for validity (not all that easy) or at least accessed within a try/catch block to trap used of undeclared identifiers or use of name declarations before initialization.

就个人而言,我建议您找到一般使用全局变量名称字符串的替代方法.想到在库上提供静态名称空间对象(例如myLibrary.data)并处理作为对象属性名称的字符串值,或在库调用中包括选项对象参数.

Personally I would recommend finding alternatives to using global variable name strings in general. Providing a static name space object on the library (e.g. myLibrary.data) and processing string values that are property names of the object, or including option object parameters in library calls, come to mind.

这篇关于window [name]等效于动态访问const和let声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆