- 当浏览器加载 HTML 页面时,首先会提供一个全局的执行环境,称为全局作用域,浏览器中是 window(既是一个窗口对象,也是全局作用域),后端环境中是 global。
- 对象是引用类型,修改对象的属性值时,先通过地址找到堆内存,然后把堆内存中的值改变。比如把之前的 obj.age = 2 改为 obj.age = 4。
- 对于函数,函数是对象数据类型,首先开辟一个内存空间(里面存的是字符串形式的函数体),函数名存储一个地址,代表当前函数本身。
变量提升 (预解释)
- 定义:在当前的作用域中,js 代码执行之前,浏览器首先会默认把所有带 var 或 function 的进行提前的声明或定义。
- 预解释只发生在当前的作用域中,比如,开始只对 window 下的进行解释,只有函数执行的时候才对函数中的声明进行解释。
- 栈内存:用来提供一个 js 代码执行的环境 -> 作用域(全局、私有)
- 堆内存:用来存储引用数据类型的值 -> 对象存储的是属性名称和属性值,函数存储的是代码字符串。
- 变量预解释时只是声明,函数预解释时声明和定义已完成。
- 函数执行时,会形成一个私有作用域,创建私有作用域就创建了一个栈内存,如果有形参,先给形参赋值。
- 闭包是一种机制,函数执行时形成一个私有作用域,保护函数内部的变量不被外界影响。
- 预解释时,不管 if 条件是否成立,都要把带 var 的变量提前声明。
- 预解释只预解释等号左边的变量,右边的值不参与。
fn() // -> TypeError :fn is not a function
var fn = function (){ };
fn2() // -> "keyi"
function fn2(){
console.log("keyi")
}
- 自执行函数在全局作用域下不预解释,当代码执行到时定义和执行一起完成。
- 函数体中 return 下面的代码虽然不再执行,但 return 后面的代码仍需预解释。return 后面跟的都是值,不进行预解释。
- ES5 中,在同一个作用域,如果变量名和函数名相同,最终只能保留一个。
fun(); // -> 2
function fun(){console.log(1)}; // window 声明+定义,开辟一个堆内存 1
fun(); // -> 2
var fun = 100; // fun = 100
function fun(){console.log(2)}; // fun 已经声明过了,放弃堆内存1 ,转向堆内存2.
fun(); // 这里不执行,100() 不是一个函数
- 函数定义的地方就是上级作用域,跟函数执行的地方无关。