概述
函数名的提升
//错误模式
f();
var f = function (){};
// TypeError: undefined is not a function
//正确模式
f();
function f(){}
//上面代码等同于
var f;
f();
f = function (){};<strong>
</strong>
函数作用域
内部的变量提升
与全局作用域一样,函数作用域内部也会产生“变量提升”现象。var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部。
(function foo(x) {
if (x > 100) {
var tmp = x - 100;
}
alert(tmp);
})(101);
// 1
参数
默认值
通过下面的方法,可以为函数的参数设置默认值。
function f(a){
a = a || 1;
return a;
}
f('') // 1
f(0) // 1
上面代码的||表示“或运算”,即如果a有值,则返回a,否则返回事先设定的默认值(上例为1)。这种写法会对a进行一次布尔运算,只有为true时,才会返回a。可是,除了undefined以外,0、空字符、null等的布尔值也是false。也就是说,在上面的函数中不能让a等于0或空字符串,否则在明明有参数的情况下,也会返回默认值。为了避免这个问题,可以采用下面更精确的写法。
function f(a){
(a !== undefined && a != null)?(a = a):(a = 1);
return a;
}
f('') // ""
f(0) // 0
arguments对象
与数组的关系
要让arguments对象使用数组方法,真正的解决方法是将arguments转为真正的数组。下面是两种常用的转换方法:slice方法和逐一填入新数组。
var args = Array.prototype.slice.call(arguments);
// or
var args = [];
for(var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
其他知识点
闭包
闭包(closure)就是定义在函数体内部的函数。更理论性的表达是,闭包是函数与其生成时所在的作用域对象(scope object)的一种结合。
function f() {
var c = function (){};
}
上面的代码中,c是定义在函数f内部的函数,就是闭包。闭包的特点在于,在函数外部可以读取函数的内部变量。
function f() {
var v = 1;
var c = function (){
return v;
};
return c;
}
var o = f();
o();
// 1
上面代码表示,原先在函数f外部,我们是没有办法读取内部变量v的。但是,借助闭包c,可以读到这个变量。
闭包不仅可以读取函数内部变量,还可以使得内部变量记住上一次调用时的运算结果。
function fn(a) {
return function () {
return a++;
}
}
var o = fn(1);
o() // 1
o() // 2
o() // 3
上面代码表示,函数内部的start变量,每一次调用时都是在上一次调用时的值的基础上进行计算的。