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)将它们转换为字符串,那么实际上我会因为当前的实现而损失性能。
无论如何,当前 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}},因此,除非我们在连接原始值,否则这不是一个选项。

详细信息
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 使用实际上是有问题?

Kevin Neaton,他打开了 CLJS-847,在生产中使用了只解决高阶情况的补丁,并且他说该补丁为他们解决了问题。他不受 str 宏情况的影響,因为它要么已经使用了 ''+x(已应用 CLJS-801)或使用了 {{[x].join('')}}(尚未在 Safari 6.0.5 中测试,但可能工作)。

如果在使用str宏时遇到 ''+x 问题,那么只要应用了CLJS-847,使用字符串函数的 ''+x 同样会出现问题。

我还没有 pull down 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发表的评论

这个bug现在可以重新打开吗?如果我的理解正确,修复应该影响 https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642,但此代码仍在HEAD中。

...