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

欢迎!请查看关于页面,了解更多这个功能的详细信息。

0
ClojureScript

示例

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

问题在于ClojureScript使用连接来将值转换为字符串,而对于重写了valueOf()方法的对象,这种做法并不好。

在js中的示例

`
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
by

评论者:dnolen

使用{{String}}的问题似乎是在打印时对性能造成了巨大的影响,详细信息请参考 http://jsperf.com/string-vs-tostring2/6

除非有出色的解决方案,否则这最好在用户代码中解决/绕过。

0
by

由nbeloglazov发表的评论:

数组连接在字符串和数字上性能更好,但在对象上表现较差,所以它并不是一个明显的性能损失。如果我在处理对象,并使用(str)将它们转换为字符串,那么实际上我可能会因为当前实现而损失性能。
无论如何,当前str的实现是错误的,因为它不遵循toString方法。这正是str函数应该执行的。我相信编译器应该首先正确,然后再考虑性能问题。

0
by

评论者:dnolen

抱歉,我重新审视这个问题,我认为真正的问题是我们需要撤销CLJS-801。

0
by

评论者:dnolen

已将CLJS-801在master中回滚

0
by

评论者: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()}} 正常,但如果检测到将引发 CLJS-847。(可以在启动时进行特殊化。)
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

bq. 有任何证据表明 str 的更高使用率实际上存在问题吗?

开启了 CLJS-847 的 Kevin Neaton 正在使用一个只在生产环境中解决高阶问题的补丁,他说这个补丁解决了他们的问题。由于它要么使用了 ''+x(已有 CLJS-801 应用)要么使用 {{[x].join('')}}(尚未与 Safari 6.0.5 进行测试,但可能可以正常工作),因此对他使用 str 宏已不受影响。

所以,如果我们使用 ''+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

评论者: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

评论者:favila

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

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

0

由nbeloglazov发表的评论:

在同时能否重新打开此缺陷?如果理解正确,修复应该会影响 https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642,但此代码仍然存在于 HEAD。

...