是否有一种在香草JavaScript中聆听/代理变量的方法?

发布于 2025-01-29 17:01:24 字数 724 浏览 4 评论 0原文

我正在构建一个网络框架,例如React;我想改善反应的一件事是状态。

我的想法是像Svelte这样的想法,使用状态您只需创建一个普通变量(在我的情况下,在创建TE状态时可以使用功能,但在更新时可以使用函数),但是Svelte是如何通过编译,来编译,我希望它可以在香草JavaScript中工作。

从我的理解来看,这是不可能的,但是我仍然试图以某种方式破解一些东西。

因此,该状态系统的一部分是不可能的,就是知道何时设置了原始的设置并获得(setters& getters),我希望它与范围的变量一起使用。因此,我无法在window> windowglobalthis this上使用object.defineProperty。我已经四处hack了一段时间,这是我认为唯一可以使用的解决方案:

  1. 代理一个new String(String),给出了这种错误类型的蜜蜂的怪异错误,价值和东西。
  2. 代理funtion.arguments对象,但这无效。
  3. 使用symbol.tprimitive,但是我找不到没有+$ {}的方法。

但是,如您所见,它们都有问题,我陷入困境,找不到任何东西,即使没有遗产或弃用的代码,即使是hacky,即使是hacky)?谢谢你!

I'm building a web framework, something like React; one of the things which I would like to improve on React is state.

My idea is something like Svelte, to use state you just create a normal variable (in my case it would be okay to use a function when creating te state, but not when updating it), but how Svelte does this Magic is by compiling, and I would like it to work in vanilla Javascript.

From my understanding this is not exactly possible, but I've still been trying to hack something somehow.

So the part of this state system that is not possible is knowing when a primitive is set and got (setters & getters), I want it to work with scoped variables; so I can't use the Object.defineProperty on the window or globalThis. I've been hacking around for quite some time and here are the only solutions I thought have could worked:

  1. Proxing a new String(string), has given weird error of this beeing of the wrong type, unknows values, and stuff.
  2. Proxing the Funtion.arguments object, but this didn't work.
  3. Using Symbol.toPrimitive, but I couldn't find a way of using it without a + or ${}.

But as you can see they all have problems, I'm stuck and can't find anything, is there any (even if hacky, though without legacy or deprecated code) way to do this? Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

空城旧梦 2025-02-05 17:01:24

您无法做您在JavaScript中描述的事情。您不能代表原始的原始方式,并且只有在读取或设置a variable 时,只有在A property of时,就不能以其他方式运行代码(getter,setter)读取或设置对象。

严格模式在其中有一个带有getters和setter的对象,然后将其放入用于使用语句的使用来解决自由主义标识符的环境中,但同样,它是不允许的严格模式下的充分理由(这是模块和其他创建新上下文的机制的默认原因,例如class的主体)。

我不愿举一个例子,但是出于完整性:

// This only works in loose mode, not strict mode
let a = 0;
const obj = {
    get a() {
        console.log(`Getter called, returning a = ${a}`);
        return a;
    },
    set a(value) {
        console.log(`Setter called, setting a = ${value}`);
        a = value;
    }
};
with (obj) {
    console.log(a);
    a = 42;
    console.log(a);
}


您更新的问题:

我的想法就像Svelte一样,使用状态您只需创建一个普通变量...但是Svelte是如何通过编译来完成这种魔术的,我希望它能在Vanilla Javascript中使用。

我不会尝试使用独立变量来完成此操作,让用户提供状态对象并将其数据属性转换为getter/setter组合(或用新的带有getter/setter组合等的版本:):

// Userland code provides a state object
const state = {
    a: 0,
    b: "hi",
};

// Your framework code converts it to using getters/setters
function enhance(obj) {
    const descrs = Object.getOwnPropertyDescriptors(obj);
    for (const key of Object.keys(descrs)) {
        const descr = descrs[key];
        if (descr.configurable && "value" in descr && typeof descr.value !== "function") {
            // A simple data property; wrap it in getter/setter
            let value = descr.value;
            if (typeof value === "object") {
                enhance(value);
            } else {
                Object.defineProperty(obj, key, {
                    get() {
                        console.log(`Getter called, returning ${key} = ${value}`);
                        return value;
                    },
                    set(newValue) {
                        console.log(`Setter called, setting ${key} = ${newValue}`);
                        value = newValue;
                    },
                    enumerable: descr.enumerable,
                    configurable: true,
                });
            }
        }
    }
}
enhance(state);

// Their code using the properties triggers your getter/setters:
console.log(state.a, state.b);
state.a = 42;
state.b = state.b.toUpperCase();
console.log(state.a, state.b);

You can't do what you've described in JavaScript. You can't proxy a primitive, and you can't run code some other way (getter, setter) when a variable is read or set, only when a property of an object is read or set.

There is an awful thing you can do in loose mode that's disallowed (for good reasons) in strict mode where you have an object with getters and setters that you then put into the environment used for resolving freestanding identifiers using the with statement, but again, it's disallowed for good reasons in strict mode (which is the default for modules and other mechanisms that create new contexts, like the body of a class).

I hesitate to give an example of it, but for completeness:

// This only works in loose mode, not strict mode
let a = 0;
const obj = {
    get a() {
        console.log(`Getter called, returning a = ${a}`);
        return a;
    },
    set a(value) {
        console.log(`Setter called, setting a = ${value}`);
        a = value;
    }
};
with (obj) {
    console.log(a);
    a = 42;
    console.log(a);
}


Re your updated question:

My idea is something like Svelte, to use state you just create a normal variable...but how Svelte does this this Magic is by compiling, and I would like it to work in vanilla Javascript.

I wouldn't try to do it with freestanding variables, have the user provide a state object and convert its data properties to getter/setter combinations (or replace it with a new version with getter/setter combinations, etc.):

// Userland code provides a state object
const state = {
    a: 0,
    b: "hi",
};

// Your framework code converts it to using getters/setters
function enhance(obj) {
    const descrs = Object.getOwnPropertyDescriptors(obj);
    for (const key of Object.keys(descrs)) {
        const descr = descrs[key];
        if (descr.configurable && "value" in descr && typeof descr.value !== "function") {
            // A simple data property; wrap it in getter/setter
            let value = descr.value;
            if (typeof value === "object") {
                enhance(value);
            } else {
                Object.defineProperty(obj, key, {
                    get() {
                        console.log(`Getter called, returning ${key} = ${value}`);
                        return value;
                    },
                    set(newValue) {
                        console.log(`Setter called, setting ${key} = ${newValue}`);
                        value = newValue;
                    },
                    enumerable: descr.enumerable,
                    configurable: true,
                });
            }
        }
    }
}
enhance(state);

// Their code using the properties triggers your getter/setters:
console.log(state.a, state.b);
state.a = 42;
state.b = state.b.toUpperCase();
console.log(state.a, state.b);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文