Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hoisting #84

Open
XXHolic opened this issue May 24, 2020 · 0 comments
Open

Hoisting #84

XXHolic opened this issue May 24, 2020 · 0 comments

Comments

@XXHolic
Copy link
Owner

XXHolic commented May 24, 2020

引子

关于 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 时,就成了匿名函数。

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

参考资料

🗑️

看的出来是哪个奥特曼么?

73-poster

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant