使用===来检查String.replace()是否实际执行了替换

Use === to check whether String.replace() actually performed a substitution?

本文关键字:执行 替换 是否 检查 String replace 使用      更新时间:2023-09-26

我想知道String.replace()是否实际上找到了匹配并执行了替换。由于String.replace()返回的是结果字符串,而不是执行的替换次数,因此我似乎必须将原始字符串与结果进行比较。

问题是,我应该使用===还是==进行比较?

据我所知,Mozilla文档和ECMAScript 5.1标准都没有规定,如果没有匹配,返回的字符串必须是与传入的字符串相同的对象。

另一方面,对于JavaScript的任何实现来说,返回一个未更改字符串的副本似乎是愚蠢的。

具体来说, 发生了什么?
var s = 'abc';
var t = s.replace(/d/, 'D');
console.log(s === t);     // I expect true, but am not sure
它是

  1. 保证打印true ?如果有,在哪里记录了这种行为?
  2. 未定义和不可靠的行为(即,我应该测试s == t代替,或者做一些聪明的替换回调闭包)?
  3. 未定义的行为,在实践中返回true在每个JavaScript实现?

编辑

@cookiemonster问道:

因此,您似乎并不真正想知道结果是否得到保证,而是想知道实现是否经过优化以在内部执行身份比较。对吗?

事实上,我确实把这道题搞砸了,最后它变成了一个X-Y问题。我真正想知道的是,如何检查是否发生了替换(替换的实际次数并不重要-一次或多次都是相同的)?这样做是有效的,而不需要单独的.match()或逐个字符的比较。并确保结果是由语言规范保证的。

===不能与String对象一起工作:

a = new String("foo")
a.replace(/XXX/, "") == a
> true
a.replace(/XXX/, "") === a
> false

或任何具有自定义toString方法的对象:

b  = { toString: function() { return "foo" }}
"foo".replace(/XXX/, "") == b
> true
"foo".replace(/XXX/, "") === b
> false

大多数时候,这不是一个问题,但正如他们所说的"praemonitus, praemunitus"。

回答你的更新:如这里所见,至少V8被优化为返回主题本身,如果没有替换可以做:

  int32_t* current_match = global_cache.FetchNext();
  if (current_match == NULL) {
    if (global_cache.HasException()) return isolate->heap()->exception();
    return *subject; <-------

和,虽然标准只要求两个字符串看起来是严格相等的(===),我绝对肯定的是,每个JS引擎都足够聪明,以避免对相等指针的strcmp

这没什么区别。

为什么?因为String.replace操作字符串,返回一个字符串。此外,字符串是基元,不是对象。

已经知道你有两个字符串。因此,=====在这方面是相同的。我甚至会说===是多余的

String类上的replace方法总是返回一个字符串,因此=====一样安全可靠,因为不会发生类型强制转换。其次,如果没有发生替换,===测试将返回true,因为它们包含相同的字符。

鉴于你的例子…

"Is Guaranteed to print true?如果有,在哪里记录了这种行为?"

是的,它是。=====各自使用的相等比较算法中都有记录。

  • 抽象相等比较算法

  • 严格相等比较算法

"这是未定义和不可靠的行为吗(即,我应该测试s == t,或者用替换回调闭包做一些聪明的事情)?"

不,这是定义良好的行为。见上图。=====操作符的行为相同。

"它是未定义的行为,在实践中返回true在每个JavaScript实现?"

只要实现遵循规范,它将返回true