JavaScript中函数是一等公民,所有的函数实际上是一个Function对象,与其他引用类型一样拥有着属性和方法,也可以被外界或者自身调用,也可以像传递参数一样将函数传递给另一个函数。
JavaScript中函数没有重载的概念,当定义两个同名函数的时候,前一个函数会被覆盖掉,举个栗子。
1 | function add(num){ |
为何会没有函数重载,是因为JavaScript中函数定义有以下三种,分别是函数声明,函数表达式以及使用Function构造函数。
1 | //函数声明 |
可以看到,当定义同名的函数的时候,也就相当于定义了同名的变量,故而后面的变量会覆盖掉前面的变量,另外需要注意的是JavaScript作用域中的 hoist,包括变量声明提升与函数函数提升。
对于变量来说,在ES5中var定义的变量会提升到作用域中所有的函数与语句前面,而ES6中let定义的变量则不会,let声明的变量会在其相应的代码块中建立一个暂时性死区,直至变量被声明。
1 | //var声明变量 |
对于函数来说,函数声明会被提升到作用域顶部,而函数表达式则不会,因而比较稳妥的是在最后调用函数
1 | //函数声明 |
也可以将函数作为另一个函数的结果返回,若是返回函数中保存着对外部函数的引用,会发生很好玩的情况:
1 | function closure(){ |
可以看到的是,我们在closure函数内部定义了两个局部变量,然后返回带有局部变量操作结果的匿名函数,将closure函数执行后的结果(保存着foo,bar变量引用的匿名函数)赋给handle变量,此时执行handle函数可以看到,输出了closure函数内局部变量操作的结果,此时我们称这种现象为闭包,闭包其实是一个函数,在上述栗子中便是指代的closure函数内的匿名函数。不过值得注意的是,由于闭包会携带包含它的外部函数的整个作用域,故而会很占内存,因此要及时释放变量的引用,不要让其常驻内存,不然会导致内存占用过多,最后出现内存泄漏的情况。