变量提升(预解析)
一、JavaScript引擎
JavaScript引擎的主要作用是,读取JavaScript代码进行处理和运行。
JavaScript引擎(JavaScript解释器),在执行JS代码之前 会先在当前作用域中进行预解析阶段,然后再从上到下开始逐行执行JS代码。
JS中代码执行分为两个步骤:
1.预解析 先全盘扫描当前作用域中的所有声明的变量,进行预先的分析和处理
2.执行 从上到下开始 逐行解释并运行JS代码
JS代码在运行之前,先解析当前作用域中的所有代码,获取所有被声明的变量进行预处理。
二、变量提升(预解析)
在JS代码执行之前,会把当前作用域中所有带var和带function关键字的变量 进行提前的声明和定义(赋值)。
变量提升中普通变量和函数变量
在变量提升阶段:
对于带var的普通变量 会被提前声明并被赋值为默认值undefined
对于带function的函数变量 会被提前声明并被赋值为当前函数本身
console.log(num) // undefined
var num = 100 // 代码执行的时候 才会进行赋值操作
用var定义的变量,在定义变量之前使用变量 输出得是变量的默认值undefined
console.log(fe) // function fe() { console.log('fe') }
fe() // 'fe'
function fe() {
console.log('fe')
}
用function定义的函数变量,在定义之前使用,输出的函数是被提前定义好的函数本身,所以我们可以在函数定义之前就来使用函数。
按照正常的思维逻辑,我们本应该是在定义了变量之后才可以使用变量。但在JS中由于存在变量提升的原因 导致出现了上面👆的现象。
变量提升结束之后,代码开始从上到下逐行解释并运行
三、作用域(栈内存)
作用域(栈内存),供JS代码执行的环境,也是用来保存基本数据类型的值。
JS中的作用域
全局作用域(window) 当打开页面时,浏览器为了执行全局中的所有代码 而提供的JS执行的环境
函数作用域(私有作用域) 当函数执行的时候,为了执行函数体里的代码,而提供的JS执行的环境
块级作用域(私有作用域) 在代码块中{},使用ES6提供的let const 形成的作用域
只要是想执行JS代码 就需要提供一个作用域(栈内存)让代码在里面执行,比如 你想要踢足球 你就需要有一个能踢足球的活动场地(所谓足球场)。
全局指的是 页面中的整个script
<script>
// 全局中的代码
</script>
全局变量和私有变量
全局变量 在全局作用域中声明的变量(全局变量参加的是全局中的变量提升)
私有变量 在私有作用域中声明的变量(私有变量参加的是私有作用域中的变量提升)
var boy = 'boy' // 全局变量
function fn(num) { // num 形参变量也属于函数中的私有变量
var girl = 'girl' // girl 函数中的私有变量
}
变量提升只发生在当前作用域中
当打开页面的时候,最先进行的是全局作用域中的变量提升。 当函数执行的时候,进行的是函数作用域中的变量提升。
console.log(a)
var a = 'java'
function fn() {
console.log(s)
var s = 'script'
}