请在 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带来的问题是打印时性能严重影响,请参考http://jsperf.com/string-vs-tostring2/6

除非提出出色的想法,否则似乎最好在用户代码中解决这个问题。

0

评论由 nbeloglazov 发布

在字符串和数字上,append操作性能更佳,但在对象上性能较差,因此并不是明显的性能损耗。如果我大量使用对象并将它们转换为字符串,那么实际上我会因为当前实现而失去性能。
无论如何,当前的str实现是不正确的,因为它不尊重toString方法。这正是str函数应该做的事情。我相信编译器应该首先确保正确性,然后再考虑性能。

0

评论者:dnolen

抱歉再次查看,我认为真正的问题是,我们只需要回滚CLJS-801。

0

评论者:dnolen

在master中回滚CLJS-801

0

评论者:favila

CLJS-801仅处理str宏。因为我们仍然有CLJS-847导致的str函数问题吗?https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642(另外,如果在那里使用toString,Safari 6.0.5会崩溃。也许我们需要{{[o].join('')}}?根据错误的所在地,这可能在Safari 6.0.5中也是错误的。)

我们需要非常具体地做的是以某种方式获取对象上进行(在 ECMASCRIPT 术语中){{ToString}}抽象操作的结果(或者带有字符串提示的底层{{ToPrimitive}}抽象操作)。使用加运算符进行字符串连接

在我看来,有以下选项

  • {{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()}},但如果检测到{{String(x)}}则会触发 CLJS-847。可以在启动时进行优化。
0

评论者:dnolen

是否有使用 str 较高确实有问题证据?

0

评论者:favila

使用加运算符进行字符串连接使用了未提示的{{ToPrimitive}}抽象调用(它通常会尝试{{x.valueOf()}},然后是{{x.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.0.5,我们就无关紧要。

0

评论者:favila

引用。是否有使用 str 较高确实有问题证据?

提出 CLJS-847 的 Kevin Neaton 在生产中使用了仅针对高阶情况的补丁,他表示补丁修复了他们的问题。他对 str 宏的情况没有影响,因为它要么已经使用''+x(已应用 CLJS-801)或者使用了 {{[x].join('')}}(尚未在 Safari 6.0.5 中测试,但可能起作用)。

如果我们使用 str 宏中的 ''+x 出现问题,那么只要应用了 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: x.toString() 在 Safari 6.0.5 上失效。解决方案是 ''+x(只在 str 宏中使用)。
CLJS-890: ''+x 对于定义了 valueOf 方法的对象没有给出预期结果。期望调用 x.toString(),而不是 x.valueOf().toString()。解决方案是使用数组连接代替字符串连接在 str 宏中,但这不解决 CLJS-847 中的 ''+x 解决方案。

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

0
by

评论者:favila

bq. 解决方案是 ''+x(只在 str 宏中使用)。

我的意思是“解决方案是 ''+x(只在 str 函数 中使用)。"

0
by

评论由 nbeloglazov 发布

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

...