2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请查看 关于 页面获取更多关于这个网站如何运作的信息。

0
ClojureScript
重新标记

specify! 隐式依赖于提供的对象是可扩展的,以便提供协议实现。以下是一个来自 REPL 的快速演示。

cljs.user> (def obj #js {:current nil})
[#js {:current nil}]
cljs.user> (js/Object.preventExtensions obj)
{"current" nil}
cljs.user> (specify! obj
              IDeref
              (-deref [^js this] (.-current this)))
{"current" nil}

请注意,`reify` 也没有记录这一要求。这导致了一些令人困惑的情况,例如,由 JavaScript 库(例如 React)返回的非可扩展对象无法扩展,而用户对 why 也不能明白。

类似地,当对象不可扩展时,`set!` 会静默失败。

cljs.user> (set! (.-foo obj) "bar")
"bar"
cljs.user> obj
{"current" nil}

goog.object/set 可以检测到这一点并引发错误。

cljs.user> (goog.object/set obj "foo" "bar")    
Execution error (TypeError) at (<cljs repl>:1).
Cannot add property foo, object is not extensible
:repl/exception!
在进一步的调查中,我发现 `goog.object/set` 能够检测到这个错误,因为它默认启用了严格模式。不幸的是,`cljs.compiler` 中 `set!` 的定义没有提供让赋值以严格模式运行的一种简单方法,并且启用它有很大可能破坏现有代码,因为严格模式会使得许多操作成为错误。

1 个回答

0
...