函数表达式

527 阅读2分钟

导言

本章学习内容:

  • 函数表达式的特征
  • 使用函数实现递归
  • 使用闭包定义私有变量

函数表达式是javaScript中的一个既强大又容易令人困惑的特征。我们知道定义函数的方式有两种:

  • 函数声明
  • 函数表达式

而函数声明的语法是这样的

function functionName(arg1,arg2) {
    // 函数体
}

通过name 属性可以访问到函数指定的名字。

functionName.name // 'functionName'

关于函数声明,它的一个重要特征就是函数声明提升,意思是在执行代码之前会先读取函数声明。这就意味着可以把函数声明放在调用它的语句后面。

say();
function say() {
    console.log('hello')
}

另一种创建函数的方式是使用函数表达式

var functionName = function(arg0,arg1) {
    // 函数体
}

这种情况下创建的函数叫做匿名函数,因为function 关键字后面没有标识符。

理解函数提升的关键,就是理解函数声明与函数表达式之间的区别

例如,执行以下代码的结果可能会让人意想不到:

// 不要这样做
if(condition) {
    function sayHi() {
        console.log('Hi')
    }
} else {
    function sayHi() {
        console.log('Yo')
    }
}

递归

递归函数在一个函数通过名字调用自身的情况下构成的.

function factor(num) {
    if(num <= 1) {
        return 1;
    } else {
        return num * factor(num - 1);
    }
}

这个一个经典的递归阶乘函数。但是可能有有点问题。

var anthor = factor;
factor = null;
anthor(4); // 出错

在这种情况下,使用 arguemnts.callee 可以解决这个问题。

arguments.callee是一个指向正在执行的函数的指针,因此可以用它来实现对函数的递归调用

function factor(num) {
    if(num < 1) {
        return 1;
    } else {
        return num * arguments.callee(num - 1);
    }
}

闭包

闭包是指有权访问另一个函数作用域中的变量的函数。
创建闭包的常见方式,就是在一个函数内部创建另一个函数,仍以前面的实例为主:

function createComparisonFunction(propertyName) {
    return function(object1,object2) {
        var value1 = object1[propertyName];
        var value2 = object2[propertyName];
        
        if(value1 < value2) {
            return -1;
        } else if(value2 < value1) {
            return 1;
        } else {
            return 0;
        }
    }
}