zoukankan      html  css  js  c++  java
  • 函数声明与函数表达式

    定义函数的方式有2种:
    1. 函数声明
    2. 函数表达式
    函数声明的形式
    function functionName(arg1,arg2){}
    

      

    关于函数声明,它有一个重要的特性就是函数声明提升,意思是在执行代码之前会先读取函数声明。
    这就意味着可以把函数声明放在调用它的语句后面。
    <script>
    sayHi();
    function sayHi(){
     alert("hi,world")
    }
    console.log(sayHi.name) //输出sayHi,这是sayHi(){} 的name
    </script>
    

      

    这个例子不会抛出错误,因为在代码执行之前会读取函数声明。
    第二种创建函数的方式是使用函数表达式。
    最常见的创建方式:
    var functionName = function(arg1,arg2){}
    

      

    这种形式看起来好像是常规的变量赋值语句,即创建一个函数并将它赋值给变量functionName
    。这种情况下创建的函数是匿名函数,因为function 关键字后面没有标识符。
    匿名函数的name属性是空字符串。这也是可以理解的,毕竟是匿名函数嘛。
    <script>
     
    sayBye();
    var sayBye = function(){
    alert("byebye");
    }
    </script>
    报错:sayBye is not a function
    

      

    理解函数提升的关键,就是理解函数声明与函数表达式之间的区别。
    <script>
     
    var flag;
    if(flag){
    function sayHi(){
    alert('hi');
    }
    }else{
    function sayHi(){
    alert('love');
    }
    };
    sayHi(); //弹出 love
    </script>
    

      

    表面上看flag的布尔值true就是用一个sayHi()定义,否则就是用另一个定义。
    实际上这在ECMAScript中属于无效语法,javascript引擎会尝试修正错误,将其转换为合理的状态。
    但是浏览器尝试修正错误的做法并不一致。大多数浏览器会返回第二个声明,忽略condition,但chrome,火狐,opera,会在flag为true时,返回以一个函数声明;因此使用这种方法很危险,不应该出现在你的代码中。不过,如果是使用函数表达式就没有什么问题了。
    <script>
    var sayBye;
    var flag;
    if(flag){
    sayBye = function(){
    alert("bye");
    }
    }else{
    sayBye = function(){
    alert("bye lizi");
    }
    };
    sayBye(); //弹出 bye lizi
    </script>
    也可以这样写:
    <script>
     
    function mult(num){
    if(num<=0){
      return num = 1;
    }else{
      return num * arguments.callee(num-1);
    }
    };
     
     
     
    alert(mult(3)) ;
    </script>
    

      

    arguments.callee指向一个正在执行的函数的指针,因此可以用它来实现对函数的递归调用
    通过使用arguments.callee代替函数名,可以确保无论怎样调用函数都不会出问题。因此,在编写地柜函数时,使用arguments.callee总比使用函数名更保险。
    但在严格模式下,不能通过脚本方位arguemnts.callee,访问这个属性会导致错误
    <script>
    'use strict';
    function mult(num){
    if(num<=0){
      return num = 1;
    }else{
      return num * arguments.callee(num-1);
    }
    };
    alert(mult(3)) ; //'caller', 'callee', and 'arguments' properties may not be accessed on strict mode //functions
    </script>
    

      

    不过,可以使用命名函数表达式来达成相同的结果。
    <script>
    var interation = (function f(num){
    if(num <=1){
      return num = 1;
    }else{
      return num * f(num-1);
    }
    })
     
    alert(interation(3));
    </script>
    

      

    以上代码创建了一个名为f()的命名函数表达式,然后将它赋值给变量interation.即使把函数赋值给了另一个变量,函数的名字f仍然有效,所以递归调用照样能正常完成。这种方式在严格模式和非严格模式下都行得通。
  • 相关阅读:
    红黑树-插入篇
    并查集
    Rabin-Karp【转载】
    KMP
    怎样花两月时间去应聘互联网公司 [转载]
    c++ 智能指针【转载】
    java序列化
    Web页面导出Excel表格
    基于jquery-UI的日期选择器
    Doc命令
  • 原文地址:https://www.cnblogs.com/lizimeme/p/6825679.html
Copyright © 2011-2022 走看看