• 彻底理解函数声明与函数表达式优先级问题


    此文讨论一下函数声明和函数表达式的一些不同之处,以及最蛋疼的优先问题,是初级文章。

    之所以写本文是因为在网上看到一篇与此相关的文章,里面给出了结果但没有分析原因,而我自己也对此有些不肯定,所以我决定自己尝试一下,并记录下来,以便以后再也不用思考这类问题。

    函数声明即function name () {}这样的代码。首先,我们要确定以下代码是完全正确的:

    t1();
    function t1(){
    console.log("t1");
    }

    即函数可以提前调用然后再声明。

    为什么可以这样?是因为javascript代码是一段一段预载的(即一组script标签),在一段代码预载完成后,会把函数声明提前到代码段的前面执行,以便在代码段的任何地方调用,所以前面的代码无错——不知道真实原理是不是如此,类似吧。

    而函数表达式,就是把一个匿名函数附给一个变量,以后想要调用这个函数时,就直接调用这个变量即可。如:

    var t1 = function(){
        console.log("new new t1");
    }
    t1();

    函数表达式就没有直接函数声明的优点,即他不能先调用再来声明。

    为什么呢?因为函数表达式是把函数附给一个变量做为他的值,而变量在没有声明之前就调用是要出错的——这个原理好懂吧?

    其实我把原理一讲,好像下面的题目就变得毫无难度了,不过我还是写出来给大家讲一下吧。题目1:

    function t1(){
        console.log("t1");
    }
    t1();
    
    function t1(){
        console.log("new t1");
    }
    t1();
    
    var t1 = function(){
        console.log("new new t1");
    }
    t1();
    
    var t1 = function (){
        console.log("new new new t1");
    }
    t1();

    请判断以上代码的输出结果。当然,肯定不会是以下结果:

    t1,
    new t1,
    new new t1,
    new new new t1

    这就涉及到前面讲的“函数声明会提前”的问题,上面的代码其实和下面的代码是一样的:

    function t1(){
        console.log("t1");
    }
    function t1(){
        console.log("new t1");
    }
    t1();
    t1();
    
    var t1 = function(){
        console.log("new new t1");
    }
    t1();
    
    var t1 = function (){
        console.log("new new new t1");
    }
    t1();

    这样一排相信大部分人一下就说出正确结果了,就是:

    new t1
    new t1
    new new t1
    new new new t1

    因为上面的代码有两个同名函数声明,而很明显后面的同名函数会覆盖之前的函数,所以只有”new t1″是生效的——这一点,没有疑问吧?

    而后面的两个var t1,则不存在提前的问题,但他们依然会覆盖同名元素,导致之前的同名元素(即t1函数声明)被替换了。

    下面把题目改一下,变成题目2:

    function t1(){
        console.log("t1");
    }
    t1();
    
    function t1(){
        console.log("new t1");
    }
    t1();
    
    var t1 = function(){
        console.log("new new t1");
    }
    t1();
    //注意下面这最后一个
    function t1(){
        console.log("new new new t1");
    }
    t1();

    这段代码要注意的是最后一个地方,即把之前的var t1的函数表达式改成了function t1()这种函数声明。这道题目结果如何呢?

    还是用前面的“提前原则”整理一下代码,整理后如下:

    function t1(){
        console.log("t1");
    }
    function t1(){
        console.log("new t1");
    }
    function t1(){
        console.log("new new new t1");
    }
    t1();
    
    t1();
    
    var t1 = function(){
        console.log("new new t1");
    }
    t1();
    t1();

    整理之后又发现,代码变得毫无难度了:前面3个同名函数声明,同样只有最后一个生效,所以紧随其后的两次t1()调用都输出new new new t1,而后面的var t1又覆盖了之前的函数声明,所以其后的两次t1()调用会输出覆盖后的结果,即new new t1

    new new new t1
    new new new t1
    new new t1
    new new t1

    题目2与题目1的代码就差别在最后一个函数的声明方式,但输出结果却面目全非。

    写成之后发现我写了一篇如此简单的文章,呃。总之你记住,直接函数声明会提前,函数表达式则不会,就行了。整理代码顺序的时候不要出错。

    原文链接

    专职web前端,精通html,css,熟练javascript.努力学习新知识中 博客文章欢迎转载,但抵制剽窃。
  • 相关阅读:
    js optional chaining operator
    Linux Bash Script conditions
    Linux Bash Script loop
    js Nullish Coalescing Operator
    js sort tricks All In One
    React Portal All In One
    最小生成树&&次小生成树
    链式前向星实现以及它的遍历
    [2015.11.8|9图论]解题代码集合
    最短路算法及其延伸
  • 原文地址:https://www.cnblogs.com/lixlib/p/3083355.html
Copyright © 2020-2023  润新知