用Javascript中的大写replace正则expression式捕获组

我想知道如何用JavaScript中的大写replace捕获组。 以下是迄今为止我尝试过的一个简化版本,它不起作用:

> a="foobar" 'foobar' > a.replace( /(f)/, "$1".toUpperCase() ) 'foobar' > a.replace( /(f)/, String.prototype.toUpperCase.apply("$1") ) 'foobar' 

你会解释这个代码有什么问题吗?

你可以传递一个函数来replace

 var r = a.replace(/(f)/, function(v) { return v.toUpperCase(); }); 

说明

 a.replace( /(f)/, "$1".toUpperCase()) 

在这个例子中,你将一个string传递给replace函数。 既然你正在使用特殊的replace语法($ N抓取第N次捕捉),你只是给出了相同的值。 toUpperCase实际上是欺骗性的,因为你只是做replacestring大写(这是有点毫无意义,因为$1字符没有大写,所以返回值仍然是"$1"

 a.replace( /(f)/, String.prototype.toUpperCase.apply("$1")) 

相信这个expression的语义是否完全一样。

我知道我迟到了,但这是一个更短的方法,更符合你最初的尝试。

 a.replace('f', String.call.bind(a.toUpperCase)); 

那么你哪里出了问题,这个新的巫术是什么?

问题1

如前所述,你试图把被调用的方法的结果作为String.prototype.replace()的第二个parameter passing,而你应该把一个引用传递给一个函数

解决scheme1

这很容易解决。 简单地删除参数和括号会给我们一个参考,而不是执行这个函数。

 a.replace('f', String.prototype.toUpperCase.apply) 

问题2

如果您现在尝试运行代码,您将会看到一个错误,指出undefined不是函数,因此无法调用。 这是因为String.prototype.toUpperCase.apply实际上是通过JavaScript的原型inheritance对Function.prototype.apply()的引用。 所以我们实际上做的更像这样

 a.replace('f', Function.prototype.apply) 

这显然不是我们的意图。 它如何知道在String.prototype.toUpperCase()上运行Function.prototype.apply () ?

解决scheme2

使用Function.prototype.bind(),我们可以创build一个Function.prototype.call的副本,其上下文专门设置为String.prototype.toUpperCase。 我们现在有以下几点

 a.replace('f', Function.prototype.apply.bind(String.prototype.toUpperCase)) 

问题3

最后一个问题是String.prototype.replace()将传递几个参数到它的replace函数。 然而, Function.prototype.apply()期望第二个参数是一个数组,而不是一个string或数字(取决于如果您使用捕获组)。 这将导致无效的参数列表错误。

解决scheme3

幸运的是,对于Function.prototype.apply() ,我们可以在Function.prototype.call()中简单地replace(它接受任意数量的参数,其中没有types限制) 。 我们现在已经到达工作代码!

 a.replace(/f/, Function.prototype.call.bind(String.prototype.toUpperCase)) 

脱落的字节!

没有人想要多次制作原型 。 相反,我们将利用事实,即我们有通过inheritance引用相同方法的对象。 作为函数的String构造函数inheritance了Function的原型。 这意味着我们可以在String.call中replaceFunction.prototype.call (实际上我们可以使用Date.call来保存更多的字节,但是这种语义更less)。

我们也可以利用我们的variables'a',因为它的原型包含了对String.prototype.toUpperCase的引用,我们可以用a.toUpperCase来replace它。 上面的3个解决scheme和这些字节保存措施的组合,就是我们如何获得这篇文章顶部的代码。