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中是可以存在闭包的。词法作用域意味着,如果在局部作用域中找不到变量,则在外部作用域中查找,依此类推,直到全局作用域。

别再害怕jS高阶函数、回调和闭包了

闭包中的异常

闭包中仅有一种异常。在JavaScript中,除了通过new Function语法创建的函数,其他每个函数都是闭包。

通常函数可以访问创建它的词法环境。但是,当函数通过new Function语法创建时,则无法访问词法环境,而是访问全局环境。

function getFunc() {
    let value = "test";
    let func = new Function('value', 'alert(value)');
    return func;
}
getFunc()(); // Undefined
因此,诸如上面代码中的func之类的函数无法访问外部变量,只能访问全局变量。
文章目录