Web/04-JavaScript基础/10.2-预编译及变量提升详解.md
2019-12-05 18:27:20 +08:00

86 lines
2.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

> 我们在上一篇文章《作用域》中简单讲过“变量提升”,今天来讲一下预编译,这对我们深入理解变量提升会有帮助。
## JavaScript 运行三部曲
- 语法分析
- 预编译
- 解释执行
## 预编译前奏
> 在讲预编译前,我们先来普及下面两个规律。
### 两个规律
**规律1任何变量如果未经声明就赋值此变量是属于 window 的属性**。(注意,无论在哪个作用域内赋值)
比如说,如果我们直接在代码里写 `console.log(a)`,这肯定会报错的,提示找不到 `a`。但如果我直接写 `a = 100`,这就不会报错,此时,这个 `a` 就是 `window.a`
**规律2一切声明的全局变量全是window的属性**。(注意,我说的是在全局作用域内声明的变量,不是说局部变量)
比如说,当我定义 `var a = 200` 时,这此时这个 `a` 就是 `window.a`
由此,我们可以看出:**window 代表了全局作用域**。
### 举例
掌握了上面两句话之后,我们再来看看下面的例子。
```javascript
function foo() {
var a = b = 100; // 连续赋值
}
foo();
console.log(window.b); // 在全局范围内访问 b
console.log(window.a); // 在全局范围内访问 a
console.log(a); // 在全局范围内访问 a但是前面没有加 window 这个关键字
```
上方代码的打印结果:
```
100
undefined
(会报错,提示 Uncaught ReferenceError: a is not defined
```
**解释**
`var a = b = 100` 这行**连续赋值**的代码等价于 `var a = (b = 100)`,其执行顺序是:
1先把 100 赋值给 b
2再声明变量 a
3再把 b 的值赋值给 a。
我们可以看到b 是未经声明的变量就被赋值了此时根据规律1这个 b 是属于 `window.b`;而 a 的作用域仅限于 foo() 函数内部,不属于 window。所以也就有了这样的打印结果。
## 参考链接
- JavaScript预编译原理分析<https://blog.csdn.net/q1056843325/article/details/52951114>
- <https://segmentfault.com/a/1190000018001871>
- 预编译及变量提升:<https://juejin.im/post/5aa6693df265da23884cb571>
- <https://juejin.im/post/5adaf8215188256712781830>
- <https://www.qqzmly.com/archives/1521>
- 宏任务&微任务相关:<https://segmentfault.com/a/1190000018134157>