Clojure 2024 述状调查!中分享您的想法.

欢迎!请查阅关于页面以了解该平台的更多详情。

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)}}
  • {{字符串原型.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宏的情况没有受影响,因为要么已经使用了''+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: 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 创建

bq. 技巧是''+x(只为str宏情况)。

我的意思是“技巧是''+x(只在str 函数 情况下)。”

0

评论由: nbeloglazov

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

...