为什么我们不必在下面的代码中向function b
传递参数?是因为我们使用的是Array类型的map方法吗?或者在JavaScript中我们可以在其他任何地方使用这样的函数吗?
有人能给出一个非常干净的解释吗?
码:
/* we have an array a*/
const a = ['a', 'b', 'c'];
/*we define a function called b to process a single element*/
const b = function(x){do something here};
/*I noticed that if we want to use function b to take care with the
elements in array a. we just need to do the following.*/
a.map(b);
函数是Javascript中的一等公民,这只是一种说法,它们可以作为变量和参数传递。
你打电话的时候在做什么
a.map(b);
基本上是打电话
[
b('a'),
b('b'),
b('c')
]
数组函数map
只使用数组中的每个参数调用给定函数(在您的情况下为b
),并将输出放在一个新数组中。所以有些论据被传递给b
,只是map
正在幕后为你做这件事。
至于你的其他问题,有很多情况你会将函数作为参数传递而不先调用它。另一个常见的功能是Array对象的reduce
。
const out = a.reduce(function (accumulator, val) {
return accumulator + ' - ' + val;
}
// out: 'a - b - c'
还有很多函数需要回调,这些函数在某种异步任务完成时调用。例如。 setTimeout
将在经过的时间之后调用给定的函数。
setTimeout(function (){
console.log("Hello World!");
}, 1000
);
// Will print "Hello World!" to console after waiting 1 second (1000 milliseconds).
并且您可以轻松编写函数以将另一个函数作为参数!只需调用您传入的函数,就像调用任何其他函数一样。
// A really basic example
// More or less the same as [0, 1, 2].map(...)
function callThreeTimes(f) {
return [
f(0),
f(1),
f(2)
]
}
// My function here returns the square of a given value
function square(val) { return val * val }
const out = callThreeTimes(square);
// out: [0, 1, 4]
你没有将参数传递给b
,因为你没有调用它。您将函数本身作为值传递。
在这里使用map
是无关紧要的;你可以直接看到发生了什么:
const a = function(x) { alert(`called with ${x}`); };
// The function is NOT called here; it's just being assigned,
// like any other kind of value. This causes "b" to become
// another name for "a".
// This is NOT the same as a(), which would call the function
// with undefined as the argument.
const b = a;
// Now we call it, and the alert happens here
b(5);
将函数传递给另一个函数的方式相同,因为它只是另一种赋值形式。
这很有用,因为即使您自己不知道参数是什么,您也可以告诉其他代码如何做某事。在map
的特定情况下,它为您循环遍历数组并为每个元素调用一次函数。你不想调用传递给map
的函数,因为map
的全部目的是为你调用函数。
map接受函数作为参数,并为数组的每个元素执行提供的函数。这里传递函数b作为映射参数,因此map对数组a的每个元素执行函数b。所以你不需要在这里传递参数到函数b,map会处理这个问题。
为什么我们不必在这里将参数传递给函数b?
仅仅因为根据spec,map
隐含地将b
称为3。
使用三个参数调用callbackfn:元素的值,元素的索引和被遍历的对象
对于数组中的每个元素,使用这三个参数调用回调函数
a
,b
和c
在你的情况下)b
本身(被穿越的物体)。为什么没有括号?
当您将函数作为参数传递给sort方法时,它在函数名后面没有括号。这是因为该函数不应该被调用,而是在那里而是map方法来引用这个函数,以便它可以在尝试映射数组时根据需要调用它。
为什么不采取任何论点?
现在我们知道map会相应地调用这个回调函数,所以当map调用它时,它会在调用它时隐式地将参数传递给它。
例如,如果这将是sort的回调,那么传递的参数将是当前元素和下一个元素。如果这是map的回调,那么参数将是当前值,索引,数组。
您可能听说过javascript中的函数是一等公民。如果你查看来自MDN map的文档,你会发现map函数接受一个最多有3个参数的回调,第一个是currentValue
所以让我们分解吧。在上面的数组上执行映射的一个非常明确的例子就是这个
a.map(function(currentValue, index, array){
// here you can access the 3 parameters from the function declaration
});
在数组的每次迭代时调用此函数。由于函数在javascript中非常灵活,因此如果您愿意,您只能声明1个参数,甚至不能。
a.map(function(currentValue){
// we need only the current value
});
JavaScript中的每个函数都是一个Function对象。 Source here
这意味着每个函数只是内存中的一个引用,这意味着它可以直接指定为匿名函数(我们上面的情况),或者像之前一样声明
function b(currentValue){
// this will be called on each item in the array
};
a.map(b)
这段代码迭代数组中的每个元素并调用我们传递的引用(函数b)。它实际上用文档中的所有3个参数调用它。
[
b('a',0,a),
b('b',1,a),
b('c',1,a)
]
但由于我们的function b
只声明了一个,我们只能访问该值。其他参数存储在所谓的Arguments object中
从这里开始JavaScript中的每个函数都是一个Function对象,它使每个函数都引用一个特定的内存位置,这最终使我们有很大的灵活性将函数作为参数传递给我们,但我们想要(通过匿名函数显式) ,或通过函数声明隐含(引用))
在JavaScript中,函数只是另一种类型的对象。
不带参数调用函数的过程如下。这将始终执行该函数并返回函数的返回值。
var returnValue = b();
删除括号将把函数本身视为变量,可以在其他变量,参数等中传递。
var myFunction = b;
在任何时候,对“函数变量”添加括号将执行它引用的函数并返回返回值。
var returnValue = myFunction();
var sameReturnValue = b();
所以map()接受一个参数,它是函数类型(没有括号)。然后,它将为数组中的每个元素调用此函数(括号)。
您将在下面找到如何使用地图功能:
第一个Methode
incrementByOne = function (element) {
return element + 1;
}
myArray = [1,2,3,4];
myArray.map(incrementByOne); // returns [2,3,4,5]
第二种方法
myArray = [0,1,2,3];
myArray.map(function (element) {
return element + 1;
}); // returns [1,2,3,4]
第三个方法
myArray = [1,2,3,4];
myArray.map(element => {
return element + 1;
});