定义函数有两种方式:函数声明和函数表达式。
函数声明:
1 | function functionName(arg0, arg1, ...){ |
函数声明,一个重要特征是函数声明提升(function declaration hoisting),在执行代码之前会先读取声明。意味着可以把函数声明放在调用它的语句后面。
1 | sayHi(); |
函数表达式:
1 | var functionName = function()(arg0, arg1, ...){ |
形式类似常规的变量赋值语句,即创建一个函数并将它赋值给变量functionName。这种情况下创建的函数叫做匿名函数(anonymous function),因为function关键字后面灭有标识符。
函数表达式与其他表达式一样,在使用前必须先赋值。
理解函数提升的关键就是理解函数声明与函数表达式之间的区别。
递归
1 | function factorial(num){ |
使用arguments.callee虽然能够解耦,但是在严格模式下,访问这个属性会导致错误。
1 | var factorial = (function f(num){ |
上述代码创建了一个名为f()的命名函数表达式,然后将它赋值给变量factorial。即便把函数赋值给另一个变量,函数的名字f仍然有效,所以递归调用照样能正确完成。
闭包
闭包,是值有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
闭包与变量
作用域链的配置机制,会引出一个副作用,即闭包只能取得包含函数中任何变量的最后一个值。
1 | function createFunctions(){ |
私有变量
严格讲,Javascript中没有私有成员概念。但有私有变量的概念。任何定义在函数中的变量,都可以认为是私有变量,因为函数外部不能访问这些变量。