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

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

我正在尝试为函数 return 赋值。我知道这乍一看可能听起来很愚蠢,但我正在完成的是直接引用警报(在 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 的能力非常有限的情况下才有可能。唯一可以使用它的时间是在分配对象 属性 时,其中 属性 名称是动态的:

foo[bar] = baz;

函数return,不是引用也不是变量,所以分配给函数的return值是完全不可能的。

有点在正确的轨道上:

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

它将一个带点的名称解析为一个值,但同样,您不能分配到该解析值。当一个函数执行 return alert 时,它 returns alert 引用 ,类似于 function () { ... }。所以你要做的相当于:

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

那是行不通的。您不能 return 一个“名称”,您只能 return 名称所指的值。

您的函数必须 return 您正在查找的对象的 parent 对象,然后您可以分配给 属性它,例如:

ref(foo)[bar] = baz;

这相当于,例如:

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

即在window所指的对象上设置一个属性alert。这显然工作得很好。

由于上述 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), { ... }));

请注意,所讨论的对象必须在 window 上作为 属性 可用(或者您可以传递给 assign 的其他根对象);没有(理智的)方式以这种方式分配给 letconst 或任何局部函数变量。

例如这可能有效:

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

这并没有发生:

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