zoukankan      html  css  js  c++  java
  • 提升

    关于提升,记住几个要点,后面所有的判断套这个要点就行:

    1,执行代码时,第一步总是静态编译,编译器会解析所有声明的变量,然后绑定到相对应的作用域中,而第二步,引擎才会开始执行赋值等操作;

    2,函数声明永远优先于变量声明,同样的函数声明,后者覆盖前者;

    来看例子:

    a = 2;
    var a;
    console.log(a);

    第一步会进行分词解析,a=2,实际上会先对a进行词法分析,当前作用域下没有(注意此时还没运行到var a),因此自动在全局作用域下定义一个a变量。

    第二步,是var a,因为当前作用域(全局下)已经定义了变量a,因此该步骤被忽略。(这里直接跳过了赋值,是因为赋值是引擎的执行动作,只有在静态编辑之后,代码执行前几微妙才开始执行。)

    以上两步完成后,编译工作完成,接下来是引擎执行环节。

    第一步,对a进行赋值操作,LHS查找,直接赋值为2.

    第二步,对console进行RHS查找,然后确认console对象下有log方法,然后对a进行RHS查找,在当前作用域下找到了a为2,因此执行打印出2。

    再看例子:

    console.log(a);
    var a = 2;

    第一步,编译过程,只有var a是变量声明,因此定义变量a。

    至此,编译完成,引擎上场

    第一步,执行console.log(a),和上面一样,两次RHS,发现a未定义,因为a的赋值在它后面,所以打印undefined

    foo();
    function(){}

    为什么函数声明可以提升,因为函数声明它没有执行赋值操作,它是编译的过程就完成了,因此执行函数的时候,已经有了定义。

    foo();
    var foo = function(){}

    这个就会报错了,报什么错?TypeError,因为var foo会在编译阶段优先执行,而foo()会进行RHS查找,找到了foo,但是foo不是一个函数,不能执行,因此报类型错误。

    foo();
    
    var foo;
    
    function foo(){console.log(1)}
    
    foo = function() {console.log(2)}

    上面代码执行顺序应该是:

    function foo() {console.log(1)}
    
    var foo;
    
    foo();
    
    foo = function(){console.log(2)}

    这里foo不会被覆盖掉,因为会被忽略掉,原因参见编译第一步分词/词法分析。

    var foo;  不等于 var foo = undefined,不然上面的function foo就会被覆盖掉;

    var foo实际上是发生在编译阶段,详细过程是编译器会先检测当前作用域下是否有变量foo,如果有,这步则省略,如果没有,则在当前作用域下新增一个变量foo,注意,这里不是赋值为undefined,而仅仅是在作用域下新增该变量。为什么有这一步,为了后面引擎在执行的时候,如果遇到了foo,无论是进行LHS或者RHS查询的时候,可以在当前作用域中去查找。

    结合编译原理再来看这些代码真的非常容易理解,并且没有任何的问题。

    end

  • 相关阅读:
    MySQL中表的基本操作1
    MySQL在表中加入记录
    GDB基本命令(整合)
    (转载)Linux的epoll模型
    不做采购,不知道销售有多蠢
    我的创业体会和大公司的做事比较
    需求问题排查
    我的创业体会和大公司的做事比较
    不同技术团队的配合问题及DevOps(不错的文章,来自infoq)
    不同技术团队的配合问题及DevOps(不错的文章,来自infoq)
  • 原文地址:https://www.cnblogs.com/yanchenyu/p/9001121.html
Copyright © 2011-2022 走看看