簡體   English   中英

有沒有辦法在 vanilla Javascript 中監聽/代理變量?

[英]Is there a way of listening/proxying a variable in vanilla Javascript?

我正在構建一個 Web 框架,比如 React; 我想在 React 上改進的一件事是狀態。

我的想法類似於 Svelte,要使用狀態,您只需創建一個普通變量(在我的情況下,可以在創建 te 狀態時使用函數,但不能在更新它時使用函數),但 Svelte 如何做到這一點 Magic 是通過編譯,我希望它可以在 vanilla Javascript 中工作。

據我了解,這並不完全可能,但我仍然試圖以某種方式破解某些東西。

因此,這個狀態系統中不可能的部分是知道何時設置和獲取原語(setters & getters),我希望它與作用域變量一起工作; 所以我不能在windowglobalThis Object.defineProperty 我已經研究了很長一段時間,這是我認為唯一可行的解​​決方案:

  1. 代理一個new String(string) ,給出了這種錯誤類型、未知值和東西的奇怪錯誤。
  2. 代理Funtion.arguments對象,但這不起作用。
  3. 使用Symbol.toPrimitive ,但如果沒有+${} ,我找不到使用它的方法。

但是正如您所看到的,他們都有問題,我被卡住了,找不到任何東西,有沒有(即使是hacky,雖然沒有遺留或不推薦使用的代碼)方法來做到這一點? 謝謝!

你不能做你在 JavaScript 中描述的事情。 您不能代理原語,也不能在讀取或設置變量時以其他方式(getter、setter)運行代碼,只有在讀取或設置對象的屬性時。

您可以在松散模式下做一件可怕的事情,在嚴格模式下(有充分的理由)不允許這樣做,在嚴格模式下,您有一個帶有 getter 和 setter 的對象,然后您將其放入用於使用with語句解析獨立標識符的環境中,但同樣,在嚴格模式下有充分的理由不允許它(這是創建新上下文的模塊和其他機制的默認設置,例如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 如何做到這一點,這個 Magic 是通過編譯,我希望它在 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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM