我正在阅读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
为什么这个函数的调用会像这样嘈杂? (布尔)是演员吗?为什么演员?返回值?还是论点?为什么不(布尔值)嘈杂(0)如果它的返回值。或者噪声((布尔值)0)如果参数是正在铸造的参数。
noisy(Boolean)(0)
这一行发生了什么? f()甚至定义在哪里?
var val = f(arg);
答案 0 :(得分:21)
Boolean
是一个功能。它是您通过noisy
间接呼叫的功能。我知道,有点令人困惑,因为它看起来像一个类型的名称。但在JavaScript中,最初限制的内容(Boolean
,Number
,String
等等)是函数。当您致电Boolean
(不使用new
)时,它会尝试将您提供的参数转换为boolean
原始值并返回结果。 (请参阅规范中的§15.6.1。)
f
是noisy
函数中参数的名称。
JavaScript中的函数是一流的对象。您可以将它们作为参数传递给其他函数,就像任何其他对象一样。
当你这样做时
noisy(Boolean)(0)
有两件事正在发生。第一:
// (In effect, we're not really creating a variable...)
var x = noisy(Boolean);
这给了我们一个函数,当被调用时,将使用我们给出的参数调用Boolean
,同时也执行那些console.log
语句。这是您在noisy
(return 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);
,则会看到它返回true
。 console.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))会简单地将一个参数传递给我们的外部函数, 而没有将任何内容传递给我们的外部函数返回的内部函数。
真的很简单。现在我们理解了它,很难相信它让我们开始时头疼...... * /`