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()不会像这个问题中描述的那样工作:[a rel="nofollow" href="http://dev.clojure.org/jira/browse/CLJS-847" target="_blank">http://dev.clojure.org/jira/browse/CLJS-847

共有35条回答

0

评论者:neatonk

是否存在toString和valueOf不匹配的有效用例?例如。

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

如果不是,两个方法不匹配是否“错误”的?

0

评论者:nbeloglazov

这是一个此类用例的示例:[a rel="nofollow" href="https://github.com/processing-js/processing-js/blob/master/src/Objects/Char.js" target="_blank">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('')}}?根据Bug所在的位置,它可能在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
* Default Value(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宏的宏case的影响,因为它要么已经使用了''+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

评论者:favila

引用。我对规范本身并不太关心,只有当它在野外起作用时才关心。如果这不会影响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

评论者:favila

引用。解决方案是''+x(仅用于str宏情况)。

我的意思是"解决方案是''+x(仅用于str 函数 情况)。"

0

评论者:nbeloglazov

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

...