1

为什么将函数传递给 的最后一个参数时replace,该函数不带括号?

来自MDN

function replacer(match, p1, p2, p3, offset, string){
  // p1 is nondigits, p2 digits, and p3 non-alphanumerics
  return [p1, p2, p3].join(' - ');
};
newString = "abc12345#$*%".replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
4

6 回答 6

2

如果您添加了括号,您将评估名为 的函数表达式replacer

相反,在这里您传递了一个名为 的变量replacer,它是对该函数的引用。不是立即执行该函数,而是告诉 Javascript稍后在本机调用它时replace使用它。

我有时会想到一个比喻,就是你把枪交给别人开火,而不是你自己开的。replacer()意思是“马上开枪”,而replacer意思是“在这里,用这个开火”。这里的期望是 JavaScript 的原生replace()函数将用子弹(参数)“装枪”,然后在准备好时开火。

于 2013-09-26T18:05:06.343 回答
0

原因是因为replacer是函数指针。正如您可以拥有指向变量实例的指针一样,您也可以拥有指向函数的指针。如果括号放在了之后replacerreplacer()那么 thenreplacer将被评估为函数本身。相反,您正在做的是传递一个指向函数的指针,replacer然后该函数可以调用该函数replace

在 c++ 中:此模式的替代方案的常见用途是函数对象/函数指针。其中 struct / object 重载了 operator () 以使其像函数一样工作。但是大多数语言都有这些版本,无论它们被称为函子、回调、函数指针还是其他任何东西。

于 2013-09-26T18:28:35.350 回答
0

这里有一些细微差别,起初可能难以掌握。

如果您要添加括号,则表明您希望replacer立即被调用。这实际上不是你想要做的。

replace实际上是在寻找对函数的引用,因此您实际上是将函数作为参数传递给replace. 在内部,replace知道何时何地正确调用replacer.

于 2013-09-26T18:04:57.047 回答
0

因为当您使用带括号的函数名称 f() 时,您将调用该函数并使用结果。当您使用不带括号时,f, if 表示您正在使用函数本身。如果有帮助,请将其视为您要使用引用函数的代码,而不是它返回的值。

在您的示例中,您没有调用函数替换器并传递要替换的值。您正在将一段名为 replace 的代码传递给函数 replace ,以便函数 replace 在需要时调用它。

于 2013-09-26T18:09:28.497 回答
0

在 JavaSCript 中,函数是与其他任何对象一样的对象。它可以分配给变量、传递给函数、从函数返回等。

在这种情况下,对的引用在replacer这里被用作变量:

newString = "abc12345#$*%".replace(/([^\d]*)(\d*)([^\w]*)/, replacer);

函数本身被传递到对replace. (这可能会在内部执行该函数,至少在某些情况下是这样。)如果括号是这样添加的:

newString = "abc12345#$*%".replace(/([^\d]*)(\d*)([^\w]*)/, replacer());

然后,不是将函数本身作为参数传递,而是将函数的结果作为参数传递。该函数的结果似乎是一个字符串。但是,您调用的函数不需要字符串,它需要一个函数。(当它试图“执行”该字符串时,传递一个字符串可能会失败。)

于 2013-09-26T18:09:31.940 回答
0

这是一个callback

如果您调用replacer(),您将在replacer function没有参数的情况下运行 。

在这种情况下,replace 函数要求一个callback as the second parameter,并且 replace 方法将调用给定的可调用参数本身。

像这样想,你可以在替换函数中做这样的事情:

.replace(/([^\d]*)(\d*)([^\w]*)/, function() {
    //You can write replacer's code here as a closure
});

不是像这样定义闭包,而是告诉替换函数调用替换函数。

于 2013-09-26T18:09:50.437 回答