[a]函数声明
function functionName(arg0,arg1,arg2){ //函数体 }
[b]函数表达式:function关键字后面没有标识符的函数称为匿名函数,在把函数当成值来使用的情况下,都可以使用匿名函数
var functionName = function(arg0,arg1,arg2){ //函数体 }
【name属性】firefox、safari、chrome和opera都给函数定义了一个非标准的name属性,通过这个属性可以访问给定函数指定的名字,这个属性的值永远等于跟在function关键字后面的标识符,匿名函数的name属性为空。
function fn(){}; alert(fn.name);//fn(IE下无效) var fn = function(){}; alert(fn.name);//空 var fn = function abc(){}; alert(fn.name);//abc
函数表达式用途
【1】【函数声明提升】
[a]在执行代码之前会先读取函数声明
sayHi(); function sayHi(){ alert("Hi!"); }
[b]函数表达式在使用前必须先赋值
sayHi(); var sayHi = function(){ alert("Hi!");//报错 }
【不安全的代码】
var condition = true; if(condition){ function sayHi(){ alert("Hi"); } }else{ function sayHi(){ alert("Yo!"); } } sayHi();
除火狐外的其他浏览器没有块级作用域的概念,函数声明提升后,代码变为:
function sayHi(){ alert("Hi"); } function sayHi(){ alert("Yo!"); } var condition = true; if(condition){ }else{ } sayHi(); //后面的sayHi()函数覆盖前面的同名函数,所以弹出Yo!
而firefox有块级作用域的概念,函数声明提升,也仅仅在其作用域内提升,代码不变:
condition = true; if(condition){ function sayHi(){ alert("Hi"); } }else{ function sayHi(){ alert("Yo!"); } } sayHi(); //condition为true,弹出Hi!
遇到以上这种情况应该把函数写成函数表达式的形式
var sayHi; var condition = true; if(condition){ sayHi = function(){ alert("Hi"); } }else{ sayHi = function(){ alert("Yo!"); } } sayHi();
【2】【函数递归】一个函数通过名字调用自身
function factorial(num){ if(num <= 1){ return 1; }else{ return num*factorial(num-1); } } console.log(factorial(5));//120
【不安全的代码】
function factorial(num){ if(num <= 1){ return 1; }else{ return num*factorial(num-1); } } console.log(factorial(5));//120 var anotherFactorial = factorial; factorial = null; console.log(anotherFactorial(4));//此时factorial已经为null,但递归函数中仍然需要调用,所以报错
【arguments.callee】是一个指向正在执行的函数的指针,用它来实现对函数的递归调用
function factorial(num){ if(num <= 1){ return 1; }else{ return num*arguments.callee(num-1); } } console.log(factorial(5));//120 var anotherFactorial = factorial; factorial = null; console.log(anotherFactorial(4));//24
【使用函数表达式】严格模式下不允许使用arguments.callee,但可以使用函数表达式达到相同的效果
//创建一个名为f()的命名函数表达式,然后将它赋值给变量factorial,即便把函数赋值给了另一个变量,函数的名字f仍然有效,所以递归调用照样能正确完成。这种方式在严格模式和非严格模式下都行得通。 var factorial = function f(num){ if(num <= 1){ return 1; }else{ return num * f(num-1); } }; console.log(factorial(5));//120 var anotherFactorial = factorial; factorial = null; console.log(anotherFactorial(4));//24