zoukankan      html  css  js  c++  java
  • JavaScript Hoisting

    引子

    关于 JavaScript 提升(Hoisting),一般在实际使用的过程中,只要遵循了“先声明,后使用”的约定,很少会碰到问题。但浏览器引擎中肯定考虑各种情况,经历了这些问题,吃一堑长一智,还是总结一下。

    提升

    先看下面打印的是什么。

    console.info(a);
    a = 1;
    var a;
    console.info(a);
    

    学过 JavaScript 基础就会知道 var 声明会先提升,第一个会打印 undefined ,按顺序执行后, a 被赋值,第二个打印是 1 。基于这样的解释,个人产生的疑惑会有:

    • 为什么会提升?
    • 这个“提升”是指声明代码都提升到最上面了吗?

    带着这些疑问,去查找资料,从中了解到下面这些内容。

    JavaScript 代码在执行前都要进行编译,大部分情况下编译发生在代码执行前的几微秒(甚至更短)的时间内。编译通常会经历三个步骤:

    • 分词/词法分析(Tokenizing/Lexing) :这个过程会将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代码块被称为词法单元(token)。
    • 解析/语法分析(Parsing) :这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树。这个树被称为抽象语法树(Abstract Syntax Tree,AST)。
    • 代码生成 : 将 AST 转换为可执行代码的过程称被称为代码生成。这个过程与语言、目标平台等息息相关。

    JavaScript 引擎相对上面步骤要复杂得多,例如,在语法分析代码生成阶段有特定的步骤来对运行性能进行优化,包括对冗余元素进行优化等。

    编译的词法分析阶段基本能够知道全部(注意 eval 和 with)标识符在哪里以及是如何声明的,从而能够预测在执行过程中如何对它们进行查找。也就是说,变量和函数在内的所有声明会在代码执行前先被处理。因此实际上声明的代码的位置是不会变动的,而是在编译阶段被放入内存中。

    提升优先级

    通过上面的了解,我们知道变量和函数声明都会提升,变量名和函数名是一样的时候会如何?

    // 先变量声明,后函数声明
    console.info(b);
    var b = 1;
    function b() {
      console.info(2);
    }
    
    // 先函数声明,后变量声明
    console.info(c);
    function c() {
      console.info(3);
    }
    var c = 4;
    

    通过上面的例子可以发现:函数声明比变量声明优先提升

    函数声明和函数表达式

    函数声明语法如下:

    function name([param[, param[, ... param]]]) { statements }

    函数声明的 name 必须要有。

    函数表达式和函数声明非常相似,它们有相同的语法。

    var myFunction = function name([param[, param[, ... param]]]) { statements }

    函数表达式的 name 非必需,写上 name 可以在调用堆栈时使用,当省去 name 时,就成了匿名函数。

    函数表达式不会提升,所以不能在定义之前调用。

    参考资料

  • 相关阅读:
    如何控制input框!
    火车头采集器破解版
    记Angular与Django REST框架的一次合作(2):前端组件化——Angular
    拉勾网一些“震惊”的结论
    一个知乎重度用户眼中的知乎
    anthelion编译
    搜索引擎爬虫蜘蛛的USERAGENT大全
    Netty系列之Netty高性能之道
    python正则表达式
    Cookie的使用,详解,获取,无法互通、客户端获取Cookie、深入解析cookie
  • 原文地址:https://www.cnblogs.com/thyshare/p/13152150.html
Copyright © 2011-2022 走看看