请分享您的想法,参加2024年Clojure状态调查!

欢迎!请参阅关于页面以了解更多关于如何使用本站的信息。

0
ClojureScript

示例

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

问题在于ClojureScript使用连接(concatenation)将值转换为字符串,这对于重写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}} 抽象操作的返回值(或带有 String 提示的底层 {{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,则使用 {{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 评论

bq. 是否有证据表明“str”的高使用实际上存在问题?

CLJS-847 的提出者 Kevin Neaton,在生产中使用了一个补丁,该补丁仅解决了高阶案例问题,并表示补丁修复了他们的问题。他对 str 宏的 case 没有受影响,因为这要么已经使用了 ''+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

由: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 workaround。

更糟糕的是,Safari上的toString()错误似乎只在某些JIT级别上被触发!

0

由:favila 评论

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

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

0

评论者:nbeloglazov

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

...