函数定义方式

[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
复制代码

 

原文地址:https://www.cnblogs.com/douglasvegas/p/4810273.html