请在 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}} 的问题似乎是打印时性能影响极大,请参考 这里

除非提出非常棒的想法,否则此问题在用户代码中最佳解决方案是解决这个问题。

0 评分

由nbeloglazov做出的评论:

对于字符串和数字,append 呼叫表现得更好,但对于对象而言表现较差,这样并不算明显的性能瓶颈。如果我在操作对象并使用 (str) 将其转换为字符串,根据当前实现,性能实际上可能会下降。
无论如何,str 的当前实现是错误的,因为它不遵守 toString 方法。这正是 str 函数应该做的。我相信编译器应该首先确保正确,然后再考虑性能。

0 评分

评论由: dnolen 发布

抱歉回头再看这个问题,我相信问题实际上是我们需要回滚 CLJS-801。

0 评分

评论由: dnolen 发布

在 master 中回滚 CLJS-801

0 评分

评论由: favila 发布

CLJS-801 只处理 str 。我们是否仍然会因为 CLJS-847 而有 str 函数 问题?请参阅 这里(尽管如此,如果在其中使用 toString,Safari 6.0.5 会崩溃。也许我们需要 {{[o].join('')}}?根据错误的实际位置,这可能在 Safari 6.0.5 中也是错误的。

我们需要非常具体地做的是,以某种方式获取(在 ECMASCRIPT 的术语中)对象上(或内在的带字符串提示的 {{ToPrimitive}} 抽象操作)的 {{ToString}} 抽象操作的返回值。与加法运算符结合的字符串连接

看起来选项是

  • {{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 评分
by

评论由: dnolen 发布

是否存在任何证据表明str的使用过频实际上出问题了吗?

0 评分
by

评论由: 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 评分
by

评论由: dnolen 发布

我对规范本身并不真正关心,只关心它在野外是否重要。如果这不是 Safari 6.05 的问题,我们就不关心。

0 评分
by

评论由: favila 发布

bq. 是否存在任何证据表明str的使用过频实际上出问题了吗?

Kevin Neaton,他在CLJS-847中使用了修复更高阶情况的补丁,并表示补丁为他们解决了问题。由于使用了''+x (已应用 CLJS-801) 或使用{{[x].join('')}}(尚未在Safari 6.0.5上测试,但可能工作),因此他未受str宏情况的影響。

因此,如果我们使用''+x与str宏有问题,只要CLJS-847被应用,我们将毫无疑问地与任意字符串函数存在问题。

我还没有拉取最新版,但这有一个我认为会因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(只在字符串宏的情况下完成)。
CLJS-890: ''+x 对于定义了 valueOf 方法的对象不会得到预期结果。期望调用 x.toString() 而不是 x.valueOf().toString()。解决方案是在字符串宏中使用数组连接而不是字符串连接,但这并没有解决 CLJS-847 中的 ''+x 解决方案。

更糟糕的是,Safari 上的 toString() 错误可能只会在某些 JIT 级别才会触发!

0 评分

评论由: favila 发布

bq. 解决方案是 ''+x(只在字符串宏的情况下完成)。

我的意思是“解决方案是 ''+x(只在字符串 函数 的情况下完成)。”

0 评分

由nbeloglazov做出的评论:

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

...