JavaScript基本数据类型(8)- 变量/函数提升+var的坑点

89 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

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 定义的变量有很多的问题

  1. 变量提升问题

    console.log(a);		// undefined
    var a = 10
    
  2. 在全局作用域下,使用 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 定义了!