本文已参与「新人创作礼」活动,一起开启掘金创作之路。
JS预解析
JavaScript代码执行之前,会先对代码进行预解析,凡是只要开辟出新的栈内存都会进行预解析(比如函数执行),预解析主要有两个作用:变量提升和函数提升
-
JS 引擎运行 JS 分为两步,
1. 预解析,2. 执行代码(1),预解析 JS 引擎会把 js 里面所有的 var 还有 function 提升到当前作用域的最前面
(2),代码执行,按照代码书写的顺序从上往下执行
-
预解析分为变量解析(变脸提升)和 函数预解析(函数提升)
变量/函数提升
变量提升 就是把所有的变量申明提升到当前作用域的最前面
函数提升 就是把所有的函数申明提升到当前作用域的最前面,不调用函数
console.log(num); // undefined
var num = 10;
func(); // undefined
function func() {
console.log(data)
var data = 20;
}
fn(); // 报错
var fn = function () { console.log(666) }
真实运行状况其实是这样的:
var num; // 变量提升
function func() { // 函数提升
console.log(data)
var data = 20;
}
var fn // 变量提升
console.log(num); // undefined
num = 10;
func(); // undefined
// 函数在运行时候会开辟一个全新的私有栈内存,栈内存运行代码之前会进行代码与解析,包括变量/函数提升
// 函数内部:
/*
function() {
var data;
console.log(data);
data = 20;
}
*/
fn(); // 报错,fn的值为 undefined,只是变量提升, =后面的函数没有解析
fn = function () { console.log(666) }
运行流程图
var带来的缺点
在ES6之前,我们都是用 var 这个关键字来定义变量,但是当初作者在创建这门语言的时候没有考虑这么多,导致了var 定义的变量有很多的问题
-
变量提升问题
console.log(a); // undefined var a = 10 -
在全局作用域下,使用 var 定义的变量会变成全局变量!!!!!
console.log(screen); // Screen { availWidth: 1920...} console.log(window.screen); // Screen { availWidth: 1920...} var screen = 20; console.log(screen); // 20 console.log(window.screen); // 20- 这个是最令我奇怪的一点,在全局作用域下定义了screen这个变量,注意!是使用 var 变量定义的,与此同时 window 全局变量也有一个属性叫做 screen,但是我们发现var定义的变量居然把window.screen这个属性给覆盖了,这是特别奇怪的行为
- ES6的 let 和 const 关键字没有这些怪异的行为,大家以后定义变量不要用 var 定义了!