请在2024年Clojure调查问卷!中分享您的观点。

欢迎!有关如何工作的更多信息,请查看关于页面。

0
ClojureScript

示例

(str #js {"toString" (fn [] "hello") "valueOf" (fn [] 42)}) ; => "42"

问题在于ClojureScript使用连接字符串来转换值,这在与重写valueOf()方法的对象不兼容。

JavaScript中的示例

`
var obj = {

toString: function() { return 'hello'; },
valueOf: function() { return 42; }

};
console.log(String(obj)); => 'hello'
console.log(obj.toString()); => 'hello'
console.log('' + obj); => '42'
`

可能解决方案可能是使用String()函数。根据本问题中的描述,使用toString()不会起作用:http://dev.clojure.org/jira/browse/CLJS-847

35 答案

0

评论者为:neatonk

toString和valueOf不协调的用例是否有效?例如。

`(not= (.toString x) (js/String (.valueOf x))`

如果不,这两种方法不协调是否“不正确”?

0

评论者为:nbeloglazov

以下是一个这样的用例的示例:https://github.com/processing-js/processing-js/blob/master/src/Objects/Char.js
这就是我发现这个错误的方法。

0

评论者为:neatonk

感谢提供链接,我明白你的意思。

0

评论者:dnolen

使用 {{String}} 的问题似乎是在打印时对性能有巨大影响,具体可以参考这里

除非有绝佳的解决方案,否则这似乎最好在用户代码中解决问题/绕过。

0

评论者为:nbeloglazov

在字符串和数字上,append 的性能更好,但在对象上表现较差,因此这不是一个明显的性能打击。如果我大量处理对象并且使用 (str) 将它们转换为字符串,那么我实际上会因为当前实现而失去性能。
不管怎样,当前 str 的实现是不正确的,因为它没有遵守 toString 方法。这正是 str 函数应该做的事情。我相信编译器应该首先做到正确,然后再考虑性能。

0

评论者:dnolen

抱歉,我现在认为问题实际上是我们只需撤销 CLJS-801。

0

评论者:dnolen

在 master 中回滚了 CLJS-801

0

评论者:favila

CLJS-801只处理字符串宏。由于CLJS-847,我们还会遇到字符串函数问题吗? https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642 (即使我们在其中使用toString,Safari 6.0.5也会崩溃。也许我们需要{{[o].join('')}}?根据错误的位置,Safari 6.0.5也可能出错。

我们非常具体需要做的是以某种方式获得对象(或者在具有字符串提示的情况下使用{{ToPrimitive}}抽象操作)的(在ECMAScript术语中){{ToString}}抽象操作返回值。使用加法运算符进行字符串连接

我认为有以下几种选择

  • {{x.toString()}}:由于CLJS-847的不良
  • {{[x].join('')}}:应该可以工作(并且对于null/undefined来说做得正确),但我认为我们应该在Safari 6.0.5中进行测试。此外,这也非常慢。
  • {{String(x)}}
  • {{String.prototype.concat(x)}}
  • {{String.prototype.slice(x,0)}} {{String.prototype.substring(x,0)}} {{String.prototype.substr(x, 0)}}
  • 通常使用{{x.toString()}},但如果我们检测到会触发CLJS-847,则使用{{String(x)}}。(可在启动时进行专门化。)
0

评论者:dnolen

有证据表明频繁使用str实际上存在问题吗?

0

评论者:favila

使用加法运算符进行字符串连接使用了无提示的{{ToPrimitive}}抽象调用(它通常首先尝试{{x.valueOf()}}然后是{{x.toString()}}),然后对结果进行{{ToString}},因此除非我们正在连接原始值,否则这不是一个选项。

详细信息
ToString http://www.ecma-international.org/ecma-262/5.1/#sec-9.8
ToPrimitive http://www.ecma-international.org/ecma-262/5.1/#sec-9.1
* DefaultValue(由ToPrimitive对对象进行调用) http://www.ecma-international.org/ecma-262/5.1/#sec-8.12.8

0

评论者:dnolen

我真正关心的是规范,只有它是否影响现实世界。如果这对Safari 6.05没有影响,我们就不关心。

0

评论者:favila

引用。“有证据表明频繁使用str实际上存在问题吗?”

提出CLJS-847的Kevin Neaton在生产中使用了补丁,该补丁仅解决了高阶情况,并表示补丁为他们解决了问题。他们不受str宏案例的影响,因为它们要么已经使用''+x(应用CLJS-801)或使用{{[x].join('')}}(尚未与Safari 6.0.5一起测试,但可能有效)。

如果我们使用 ''+x 与 str 宏出现问题时,只要应用 CLJS-847,使用 ''+x 与字符串函数也会出现问题。

我还没有拉取 master 分支,但是这里有一个测试用例,我打赌它会因为 CLJS-847 补丁而失败。

(def tricky-obj #js {"toString" (fn [] "hello") "valueOf" (fn [] 42)}) (assert (= (apply str tricky-obj) "hello")) ;; 将得到 "42"

0
by

评论者:favila

bq. 我并不真的非常关心规范,只有它在野外有影响时才关心。如果这不会影响 Safari 6.05,我们就不关心了。

要弄清楚,这里有两个问题

CLJS-847: 在 Safari 6.0.5 上 x.toString() 失败。解决方案是 ''+x(仅在 str 宏情况下执行)。
CLJS-890: ''+x 对于定义了 valueOf 的对象不会得到预期的结果。期望 x.toString() 被调用,而不仅仅是 x.valueOf().toString()。解决方案是在 str 宏中使用数组连接而不是字符串连接,但这并没有解决 CLJS-847 的 ''+x 工作区。

更糟糕的是,看起来 Safari 上的 toString() 错误可能只能在特定的 JIT级别触发!

0
by

评论者:favila

bq. 解决方案是 ''+x(仅在 str 宏情况下执行)。

我的意思是 "解决方案是在 str 函数 情况下执行 ''+x。"

0
by

评论者为:nbeloglazov

这个错误bug可以在此期间重新打开吗?如果理解正确,修复应该会影响 https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642,但这段代码仍然存在于 HEAD 中。

...