清晰认识JavaScript函数

作者: integrate | 来源:发表于2015-09-05 22:12 被阅读1644次

    函数是JavaScript中最基本的要素,是基础中的基础,如果你对函数仅仅是一知半解,那基于函数构建的JavaScript知识体系也不会牢固。本人的观点:基础是最重要的东西,所以一定要彻底搞清楚。

    一、创建函数的方式

    1.1 函数申明

    单纯的使用function+函数名:

    function a() {...}
    

    两个关键点:
    一、强调单纯,申明函数的代码不归属于任何表达式
    二、必须指定函数名

    此外函数申明可以被JavaScript解释器提前执行,所以以下代码不会报错:

    // 打印:test
    a();
    
    function a() {
        console.log("test");
    }
    

    1.2 函数表达式

    1.2.1什么是表达式

    理解函数表达式,首先要搞清楚什么是表达式。从数学角度看,表达式的定义:由数字、运算符合、分组操作符()、变量组成的以求值为目的组合。关键词:以求值为目的。在编程语言中表达式是用来计算出结果的。

    1.2.2 函数表达式的定义

    在表达式中定义的函数。

    由定义可知,函数表达式并没有一个固定的写法,判断准则只有一条:函数是否定义在表达式中,或作为表达式存在。举例说明:

    // 将代码块“function() {...}”的计算结果(实质上是匿名函数的引用)赋值给a
    var a = function() {..};
    
    // 将代码块“function() {...}”的计算结果(实质上是匿名函数的引用)作为t的参数
    function t(function(){
    });
    
    // 分组操作符中的函数表达式,JavaScript解释器会自动计算()内的内容
    (function() {});
    
    // 指定函数名的函数表达式叫:命名函数表达式
    var a = function b() {...};
    

    以上示例中的function() {...}function b() {...}都是函数表达式,但是单独使用的function() {...}function b() {...}就不是函数表达式了,由此可知,函数表达式必须拥有一个上下文的环境,在此环境中,作为表达式的函数才是函数表达式,本质上就是一个表达式而已。

    函数表达式中的函数名可以省略,没有指定函数名的函数叫匿名函数,匿名函数不能单独存在,只能作为表达式存在。

    1.3 命名函数表达式

    1.3.1 存在的意义

    一般情况下函数表达式不需要指定函数名,只作为匿名函数存在,但是有一种场景必须指定名字才行:函数表达式中调用函数本身。

    var a = function b(n) {
        n--;
        if (n > 5) {
            b(n);
        }
    };
    

    你可能觉得上面的例子没有说服力,因为完全可以通过函数申明的方式实现;但是下面的例子,只能通过命名函数表达式来实现:

    function a(function b(n) {
        n--;
        if (n > 5) {
            b(n);
        }
    });
    

    该例中,函数表达式作为参数存在,如果想调用自身,只能指定函数的名字。(arguments.callee()可以实现调用函数本身,但从es5开始禁止在strict mode中使用)

    1.3.2 ie中的bug

    命名函数表达式在ECMAScript规范中指出,函数名对外不可见,只能在函数内部使用,例如:

    var a = function b() {};
    
    // 打印:b is not defined
    console.log(b);
    

    但是在ie8及ie8以下版本中,函数名却可以访问,如果你在ie8中使用了命名函数表达式,一定要注意该bug带来的影响,好在从ie9开始,微软修复了这个bug。

    二、IIFE(立即调用的函数表达式)

    在JavaScript开发中,最头疼的问题就是命名冲突,为了解决这个问题,我们首先想到的是将全部的属性与方法挂在一个全局变量上,实现单全局变量;为了追求极致,人们开始寻找0全局变量的解决方案,首先想到的就是匿名函数,为什么呢?逻辑很简单,因为它没有名字。而匿名函数只能作为函数表达式存在,所以就有了以下代码:

    (function() {...})();
    

    function() {...}是一个匿名函数,通过分组操作符包裹起来作为表达式存在,而这个表达式的计算结果显然是一个函数,既然是函数就可以通过()来调用执行。
    三、为什么说函数也是对象


    在JavaScript中有一个关键字:Function,注意F大写,它是一个构造方法,我们创建的任何函数本质上都是Function的实例,所以函数是实实在在的对象。什么时候将函数视为对象呢?在使用函数的属性或方法时,虽然有点绕,但是JavaScript就是这么设计的,函数也拥有属性与方法,比如apply、call等,这里不做展开,只给大家一个初步的概念。

    相关文章

      网友评论

      • 蚊子爸爸:其实看了楼上的讨论以后我觉得楼主没必要把概念原封不动的重新誊写一遍过来。
        既然是创作,还是要加入自己的思想。用自己的比喻和自己的说话风格。不然我们为什么不去看Javascript高级编程呢?
        我们看别人的博客更希望看到博主的思想,而不是不允许改变的格式化的文字。
        蚊子爸爸:@integrate 确实很有教科书的范儿。我个人喜欢活泼一些的风格,不过我还是会继续关注你的:)
        integrate:@oukichi JavaScript高级编程我确实没看过,没想到我的说话风格与大师的作品如此相像,我很荣幸....说实话,我对于概念的理解与描述,完全是我消化后的产物,如有雷同纯属巧合 :joy: 感觉自己好不谦虚啊,哈哈,不过我文字表达的功底太浅,尚不能将严谨与轻松融合,只能选择严谨的描述了
      • NARUTO_86:不同意这里的说法:
        “匿名函数不能单独存在,只能作为表达式存在。”
        还有这里的例子是什么情况:

        function a(function b(n) {
        n--;
        if (n > 5) {
        b(n);
        }
        });
        integrate:@luobo_tang 我的观点与你不同:我觉得概念这个东西一定要严谨,是什么就是什么,不然以后不管是看技术博客还是编写自己的技术文章,遇到这种概念性的词汇,就不能准确的理解与描述,作为发布到网络上大家能都看到的文章更应该注意措辞的严谨性,因为稍不注意就会误导新人。第二个地方,我不太理解你指的是什么,能具体一点吗?我很愿意和同行交流哈哈
        NARUTO_86:@integrate 关于“匿名函数”是否单独存在,我的看法是:只要有地方用就好可以了,“只能作为表达式存在”有点绕了。
        var a = [function () { console.log('ok') }]
        setTimeout(function () { console.log('ok') })
        最重要的是,都有一个“函数对象”创建出来了,至于“作为表达式”,我觉得不必非得这么看吧。
        第二个地方,请执行下这个代码,你这里是声明函数(function a(...)),而非调用(a(...))。
        integrate:@luobo_tang 当匿名函数单独存在的时候,JavaScript解释器会认为它是一个函数申明,而函数申明必须要有函数名,所以会报错,你可以在浏览器控制台执行:function(){};试一下;至于那个例子,实质上把function b(n){.....}当做a的参数传递而已,JavaScript中函数可以作为参数与返回值的,你应该经常遇到 :blush:
      • 040444774d8e:虽然是基础知识 但还是顶一顶
      • rainkong:不错 挺好的
      • 7f81d738b5e4:欢迎加入简书!
        integrate:@伍敏肇 :smile: 谢谢,这里写技术博客挺漂亮的

      本文标题:清晰认识JavaScript函数

      本文链接:https://www.haomeiwen.com/subject/uftrcttx.html