Javascript中的高阶函数

时间:2014-05-08 07:23:47

标签: javascript function higher-order-functions

我正在阅读Eloquent JavaScript(The new edition)并且我在更高阶函数上达成了一部分,我对以下代码中发生的事情感到困惑。

function noisy(f) {
  return function(arg) {
    console.log("calling with", arg);
    var val = f(arg);
    console.log("called with", arg, "- got", val);
    return val;
  };
}
noisy(Boolean)(0);
// → calling with 0
// → called with 0 - got false
  1. 为什么这个函数的调用会像这样嘈杂? (布尔)是演员吗?为什么演员?返回值?还是论点?为什么不(布尔值)嘈杂(0)如果它的返回值。或者噪声((布尔值)0)如果参数是正在铸造的参数。

    noisy(Boolean)(0)
    
  2. 这一行发生了什么? f()甚至定义在哪里?

    var val = f(arg);
    

5 个答案:

答案 0 :(得分:21)

  1. Boolean是一个功能。它是您通过noisy间接呼叫的功能。我知道,有点令人困惑,因为它看起来像一个类型的名称。但在JavaScript中,最初限制的内容(BooleanNumberString等等)是函数。当您致电Boolean使用new)时,它会尝试将您提供的参数转换为boolean原始值并返回结果。 (请参阅规范中的§15.6.1。)

  2. fnoisy函数中参数的名称。

  3. JavaScript中的函数是一流的对象。您可以将它们作为参数传递给其他函数,就像任何其他对象一样。

    当你这样做时

    noisy(Boolean)(0)
    

    有两件事正在发生。第一:

    // (In effect, we're not really creating a variable...)
    var x = noisy(Boolean);
    

    这给了我们一个函数,当被调用时,将使用我们给出的参数调用Boolean,同时也执行那些console.log语句。这是您在noisyreturn function(arg)...);

    中看到的功能

    然后我们称之为该功能:

    x(0);
    

    当你看到控制台输出时就是这样。由于Boolean(0)false,因此您会看到Boolean返回该值。

    这是一个更简单的例子:

    function foo(bar) {
        bar();
    }
    function testing() {
        alert("testing got called");
    }
    foo(testing);
    

    在那里,我将函数testing传递给foo。我在foo内使用的参数名称是bar。第bar();行调用该函数。

答案 1 :(得分:9)

没有()的函数是实际函数。带()的函数是函数的调用。另请注意,JavaScript是一种松散类型的语言,因此您不必声明变量类型。我已经为您的示例添加了一些评论以尝试和帮助。

// We define a function named noisy that takes in an argument named f. We are expecting f to be a function but this isn't enforced till the interpreter throws an error. 
function noisy(f) {
// Noisy returns a single item, an anonymous function. That anonymous function takes in an argument named arg
  return function(arg) {
    console.log("calling with", arg);
// Our anonymous function then takes f (It can use f because its defined inside noisy, see closures for more details) and invokes it with the argument arg and stores the result in a variable named val. 
    var val = f(arg);
    console.log("called with", arg, "- got", val);
// It now returns val
    return val;
  };
}

那么吵闹(布尔)(0)就像这样工作

f是函数Boolean

noisy返回类似这样的函数

function(arg) {
  var val = Boolean(arg);
  return val;
}

现在我们有了

我们返回的函数(0)

执行正常的

function(0) {
  var val = Boolean(0); // false
  return val;
}

答案 2 :(得分:5)

我对JS比较陌生,我也只是阅读了Eloquent Javascript,一旦我理解了函数的调用(回答你的观点1),我发现它更容易理解:

noisy(Boolean)(0);

noisy(Boolean)创建一个新函数,(0)在它之后,因为它作为参数传递给新函数。如果您回头看大于示例:

function greaterThan(n) {
  return function(m) { return m > n; };
}
var greaterThan10 = greaterThan(10);
console.log(greaterThan10(11));

也可以这样调用:

greaterThan(10)(11);

我希望这澄清你的第一个问题,为什么以这种方式调用它。

关于第二个问题。 f中的var val = f(arg);

Boolean

是输入noisy时传递到noisy(Boolean)的{​​{1}}函数。然后它被用作嘈杂函数中的参数。我也没有意识到布尔本身就是一个函数,而不仅仅是一种数据类型。正如其他人所说 - 它将你给它的参数转换为布尔值并返回结果。

因此,val变为Boolean(arg),其变为Boolean(0),其评估为false。如果您尝试拨打noisy(Boolean)(1);,则会看到它返回trueconsole.log("called with", arg, "- got", val);只记录参数(本例中为0)和评估结果(false)。

实际上,它已将布尔函数更改为记录参数和结果的函数,并返回结果。

我希望这会有所帮助。只是写它有助于我自己的理解。

答案 3 :(得分:1)

Javascript 变量没有静态数据类型。也可以为它们分配不同数据类型的变量。

JS 中没有类型转换的概念,如 JAVA 等。

函数调用中的

()对应于函数的调用。

这里,Boolean 似乎是一个高阶函数,它作为参数传递给有噪声的函数。噪声函数的结果将是

function(arg) {
  console.log("calling with", arg);
  var val = f(arg);
  console.log("called with", arg, "- got", val);
  return val;
};

带有 0 的第二个括号用于调用此结果。

这里,在上面的函数中,注意下面的行。

var val = f(arg);

这里,f 对应于之前传递的布尔函数。 arg 对应于 0。

由于返回的是val,所以表达式的结果将是Booelan(0)的结果。

答案 4 :(得分:0)

如果你仍然遇到这个问题,这就是我理解它的方式(它让我头疼......)

var array= ["a", "b", "c", "d"]
var finalArray = array.slice(2, 4); // or slice(2), since 4 is the length of this array

console.log(finalArray);

一个函数只是一个常规值。上一句是理解这里发生了什么的关键。

我们的嘈杂(f)功能是一个值。这是它的回报。

noisy(f)返回一个带参数的函数(arg)。

嘈杂(f)也接受论证(f)。内部函数(从函数内部调用的函数)可以访问传递给外部函数的变量和参数。

我们正在调用外部函数并将其传递给参数Boolean。我们的外部函数返回其内部函数,它接受一个参数(0)。 通过理解上面的内容,应该很清楚,有噪声(布尔值(0))会简单地将一个参数传递给我们的外部函数, 而没有将任何内容传递给我们的外部函数返回的内部函数。

真的很简单。现在我们理解了它,很难相信它让我们开始时头疼...... * /`