【发布时间】:2011-11-16 01:08:03
【问题描述】:
以前有几个关于 StackOverflow 的问题询问如何通过作用域链访问局部变量,例如,如果您想使用括号表示法和字符串引用局部变量,则需要 __local__["varName"] 之类的东西。到目前为止,我什至还没有找到实现这一点的最骇人听闻的方法,而且在利用我所知道的每一个技巧数小时后,我还没有想出一个方法。
它的目的是在任意无父变量上实现 getter/setter。 Object.defineProperties 或__defineGet/Setter__ 需要调用上下文。对于全局或窗口上下文中的属性,您可以实现使用 setter/getter 直接引用对象的目标。
Object.defineProperty(this, "glob", {get: function(){return "direct access"})
console.log(glob); //"direct access"
即使在使用自定义扩展的测试中,我也编译成修改后的 Chromium,该 Chromium 在上下文是实际全局上下文的任何窗口创建之前运行,甚至尝试在全局上下文中直接调用 this崩溃 我的程序,我可以顺利完成:
Object.defineProperty(Object.prototype, "define", {
value: function(name, descriptor){
Object.defineProperty(this, name, descriptor);
}
};
define("REALLYglobal", {get: function(){ return "above window context"; }});
然后它在以后创建的所有框架中都可用,作为通过指定 getter/setter 路由的全局路由。旧的 __defineGet/Setter__ 也可以在该上下文中工作,但没有指定调用它的对象(虽然在 Firefox 中不起作用,但上面的方法可以)。
所以基本上可以为对象上的任何变量定义获取/设置保护,包括直接调用对象的窗口/全局上下文(您不需要window.propname,只需propname)。这是无法引用无父范围变量的问题,这是唯一可以在可访问范围内但没有可寻址容器的类型。当然,它们也是最常用的,所以它不是极端情况。这个问题也超越了 ES6/Harmony 中代理的当前实现,因为它是一个无法使用语言语法处理本地对象容器的问题。
我希望能够这样做的原因是,它是允许重载大多数数学运算符以用于复杂对象(如数组和哈希)并导出复杂结果值的唯一障碍。在我为重载设置的对象类型上设置值的情况下,我需要能够连接到 setter。如果对象可以是全局的或者可以包含在父对象中,那没问题,这可能就是我将要使用的。 a.myObject 仍然有用,但目标是使其尽可能透明地可用。
不仅如此,能够完成这样的事情真的很有用:
var point3d = function(){
var x, y, z;
return {
get: function(){ return [x, y, z]; },
set: function(vals){ x=vals[0]; y=vals[1]; z=vals[2]; }
};
};
(这类似于 ES6 的解构,但具有更通用的应用程序来实现附加到获取/设置的功能,而不仅仅是传输复杂值)。即使是这个基本代码也会完全失败:
var x = {myname: "intercept valueOf and :set: to overload math ops!", index: 5};
x++; //x is now NaN if you don't implement a setter somehow
我不在乎这个解决方案有多么老套,在这一点上,我只是对它是否可以完成产生了强烈的好奇心,即使它需要打破所有存在的最佳实践。到目前为止,我已经让 Firefox 和 Chrome 崩溃了几百次,通过无限递归执行诸如重新定义/拦截/修改Object.prototype.valueOf/toString、Function.prototype、Function.prototype.constructor、Function.prototype.call/apply、arguments.callee.caller 等操作错误和诸如此类的尝试追溯性地对上下文进行陪审团。我唯一能做的就是用 eval 和动态构建代码块来包装整个事情,这对我来说太远了,以至于我无法实际使用。唯一其他远程成功的方法是使用with 并结合预先定义容器上的所有局部变量,但这显然对使用with 的问题非常具有侵入性。
【问题讨论】:
-
object.defineProperty应该在window上工作。但是,您无法创建局部变量,因为您无法以编程方式访问ScopeContext -
您意识到管理此问题的唯一方法是正确编译。 (My attempt at compilation)
-
这是我最后一次尝试,看看是否有人发现了我没有发现的漏洞。我有以某种方式找到解决方案的历史,这是我在 StackOverflow 上的第一个问题,因为经过大量工作后我最终还是一无所获。
-
出于好奇,您为什么要这样做?是否存在导致这种情况的现实问题?
-
它显然可以解决,但它似乎是一个明显的漏洞,确实会导致特定问题。我看到人们问的最常见的问题是尝试使用括号表示法访问局部变量,这可能非常有用。它只是通过要求在父成员或全局上下文中(在语法上)完成所有真正有用/很酷的技巧来强制对事物采取更加面向类/对象的角度。
标签: javascript scope closures local setter