别再害怕jS高阶函数、回调和闭包了
JavaScript中的HOF(高阶函数)、回调以及闭包,这些都是我们学习JavaScript过程中的拦路虎,但是如果你对它们的概念及用法理解清楚了,那么你会发现,其实它们也并不是你想象的那么可怕。
高阶函数
一个函数,如果接受函数定义作为参数,或返回一个函数,那么这个函数就称为HOF(高阶函数)。
例如:
function isEven(n) {
return n % 2 === 0;
}
function printMsg(evenFunc, num) {
const isEven = evenFunc(num);
console.log(`The number ${num} is even: ${isEven}`);
}
printMsg(isEven, 2);
在上面的代码片段中,printMsg是高阶函数,因为它接受isEven函数作为参数。
回调
回调也是函数,是作为稍后执行的参数传递给另一个函数的函数。最后一个代码片段中的isEven是回调函数。
之所以称为回调,是因为它会回到创建它的地方调用。
让我们再看一个例子。
let numbers = [1, 2, 4, 7, 3, 5, 6];
function isOddNumber(number) {
return number % 2 !== 0;
}
let oddNumbers = numbers.filter(isOddNumber);
console.log(oddNumbers); // [1, 7, 3, 5]
在上面的代码片段中,isOddNumber是回调函数。因为isOddNumber是作为参数传递给filter函数的。
回调函数可用于处理异步JavaScript。
闭包
从执行上下文中,我们知道函数在返回后会从调用栈中移除,并从执行上下文中删除。请看闭包的定义:
闭包是一个即使在外部函数返回后也可以访问外部变量的函数。
一旦外部函数返回,它就会从调用堆栈中删除并从执行上下文中删除。但是内部函数仍然可以访问外部函数变量。这个概念被称为闭包。
let x = 10;
function foo() {
let y = 20;
function bar() {
let z = 15;
return x + y + z;
}
return bar;
}
let test = foo();
test(); // 45
在上面的代码中,bar是闭包函数,即使在外部函数返回之后,它也可以访问外部变量(x和y)。
简化后的闭包定义:
闭包是记住其创建环境的函数。
当有函数从外部函数返回时,函数本身就携带了环境。
由于词法作用域,JS中是可以存在闭包的。词法作用域意味着,如果在局部作用域中找不到变量,则在外部作用域中查找,依此类推,直到全局作用域。
闭包中的异常
闭包中仅有一种异常。在JavaScript中,除了通过new Function语法创建的函数,其他每个函数都是闭包。
通常函数可以访问创建它的词法环境。但是,当函数通过new Function语法创建时,则无法访问词法环境,而是访问全局环境。
function getFunc() {
let value = "test";
let func = new Function('value', 'alert(value)');
return func;
}
getFunc()(); // Undefined
因此,诸如上面代码中的func之类的函数无法访问外部变量,只能访问全局变量。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。