为什么我不能使用左手赋值来修改函数结果的值?

Why can't I use left hand assignment to modify value of function result?

提问人:jeffbRTC 提问时间:2/2/2021 最后编辑:jeffbRTC 更新时间:2/2/2021 访问量:143

问:

我正在尝试为函数返回给我的内容分配一个值。我知道乍一看这听起来可能很愚蠢,但我正在完成的是直接引用警报(在 C++ 中,这称为左值)并对其进行修改。

function foo() {
  return alert;
}

foo() = "zoo"

var name = "alert";
var ref = (reference) => reference.split('.').reduce((o,i)=>o[i], window)

ref(name) = new Proxy(ref(name), {
    apply: (target, thisArg, args) => {

        console.log(thisArg)
        console.log(args)
    
        return "Alert called";
    }
});

我现在可以做,

var name = "alert";    
window[name] = new Proxy(window[name], window), {
    apply: (target, thisArg, args) => {

        console.log(thisArg)
        console.log(args)
    
        return "Alert called";
    }
});

但是对于复杂的对象,它会变得复杂,例如"HTMLCollection.prototype"

即使使用 eval,它也不起作用

var name = "alert";

eval(name) = new Proxy(eval(name), {
    apply: (target, thisArg, args) => {

        console.log(thisArg)
        console.log(args)
    
        return "Alert called";
    }
});
JavaScript 赋值运算符

评论

2赞 deceze 2/2/2021
不。函数返回值,而不是变量或引用。将值分配给值是没有意义的。
0赞 Scott Marcus 2/2/2021
你对这里的分配有错误的想法。 是对象的方法,并且该方法不返回值。这就是您的代码尝试执行的操作,引用方法的返回值。如果你想直接访问该功能,你需要编写类似 的东西,这本质上是一种缓存警报功能的方法。但是,在这里这样做有什么好处呢?alert()windowalert()alertconst foo = window.alert
0赞 Dave Newton 2/2/2021
@jeffbRTC 所以你正在尝试与任意对象的字符串名称一起使用?我仍然想不出这样做的好理由,但如果这是你唯一的目标并且你控制输入,你总是可以使用. 显然是邪恶的,但在某些情况下,它是最干净的解决方案,即使在您处理消毒之后也是如此。Proxyevaleval
0赞 jeffbRTC 2/2/2021
@DaveNewton正确。但是您仍然需要一个直接引用,然后将其分配给代理,因此在这种情况下,甚至 eval 都不起作用,浏览器抛出错误,左手分配......
0赞 deceze 2/2/2021
您可以执行类似 的操作,其中函数在内部展开带点的对象名称,直到倒数第二个嵌套对象,并在最后一级执行此操作。你不能以任何其他方式对变量进行赋值(这是你真正要问的)。assign('foo.bar', new Proxy(...))assigno[i] = proxy

答:

1赞 deceze 2/2/2021 #1

你几乎是在要求变量变量,即按名称解析变量以进行赋值,而这只有在 Javascript 中非常非常有限的容量中才有可能。唯一可以使用它的时间是在分配属性名称为动态的对象属性时:

foo[bar] = baz;

函数返回值,而不是引用或变量,因此分配给函数的返回是完全不可启动的。

在这方面走在正确的轨道上:

(reference) => reference.split('.').reduce((o,i)=>o[i], window)

它将带点名称解析为值,但同样,您不能分配给该解析的值。当函数执行 时,它返回 alert 引用的值,类似于 。因此,您尝试执行的操作等同于:return alertfunction () { ... }

function () { ... } = new Proxy(...)

这是行不通的。你不能是“name”,你只能返回 name 引用的值。return

你的函数必须返回你要找的那个的父对象,然后你可以分配给它的属性,例如:

ref(foo)[bar] = baz;

这相当于,例如:

window['alert'] = new Proxy(...)

即,在引用的对象上设置属性。这显然很好用。alertwindow

由于上述函数的使用有些笨拙,因此最好将其包装成如下所示的函数:ref

assign(foo, baz)

这可能看起来像这样:

function assign(name, obj) {
    const path = name.split('.');
    const parent = path.slice(0, -1).reduce((o, i) => o[i], window);
    parent[path[path.length - 1]] = obj;
}

const name = 'foo.bar.baz';
assign(name, new Proxy(ref(name), { ... }));

请注意,有问题的对象必须作为 上的属性可用 though(或您可以传递到的其他根对象);没有(理智的)方法可以以这种方式分配给 OR 或任何局部函数变量。windowassignletconst

例如,这可以工作:

let foo = { bar: {} };
assign('bar', new Proxy(...), foo);

这不会发生:

let foo = {};
assign('foo', new Proxy(...));

评论

0赞 jeffbRTC 2/2/2021
谢谢你。在问这个问题时,我考虑的是C++,因为在C++中,可以用左值做我要求的事情,我想Javascript不同。
0赞 deceze 2/2/2021
是的,不要将 Javascript 与 C 混淆。