您的位置:首页 > Web前端 > JavaScript

JS深入理解作用域、作用域链,变量提升

2020-05-31 13:07 76 查看

1、作用域
(1)全局作用域:在浏览器加载我们HTML页面的时候,首先会开辟一个供js代码执行的环境,即全局作用域,这是一个栈内存
(2)私有作用域:函数执行时,开辟一个新的栈内存,形成私有作用域
2、基本数据类型与引用数据类型区别?
基本数据类型:String,Number,Boolean,Null,Undefined,直接将变量值存储在栈中
引用数据类型:将指针存储在栈中,指针指向堆内存
3、变量提升(js执行之前,浏览器将var提前声明为undefined,将function提前声明和定义)
变量提升只发生在当前作用域:
(1)开始加载页面时,只对全局变量进行提升,在函数内的声明的变量不被提升。
(2)执行函数时,私有作用域形成后,先形参赋值,然后变量提升,最后执行代码
4、带var和不带的区别 ----作用域链
(1)全局作用域下:
不加var是window的一个属性,不是变量,不会被变量提升
window下的属性与全局变量存在映射,全局变量会被赋值给window对象相同属性

console.log(a);//undefined
console.log(b);//报错,没有这个变量,也没有被提升声明
var a = 12;// a会被变量提升,window.a也为12
b = 5 //window.b = 5;window的b属性为5
console.log(window.b);//5
console.log(b);//5

(2)私有作用域下,是否带var的区别
带var是私有作用域下的变量,函数执行时,刚进去函数体会被提升,和外界无关。
不带var不是私有变量,会像上级逐级查找,直到找到或到window(此查找机制叫做“”作用域链“”),在私有作用域下操作不带var的变量,是在操作外界

console.log(a,b); // undefined undefined 全局变量被提升
var a = 12,
b = 12;   //逗号为缩写

function fn(){
console.log(a,b); //undefined 12 私有变量a被变量提升为undefined,b沿着作用域链查找到window,输出13
var a = b = 13;
console.log(a,b);//13 13 私有变量被定义为13,window.b被修改为13
}
fn();
console.log(a,b); //12 13  全局a仍然为12,window.b在方法内被修改为13

5、特殊情况的变量提升
(1)匿名函数被变量提升为undefied(只提升等号左边)

a(); //a 经过变量提升,可以运行
b();//报错,因为匿名函数会被变量提升为undefied,not a function
function a(){
console.log(a);
}
var b = function() {
console.log(b);
}

(2)添加判断下的变量提升
不管判断条件是否成立,都会进行变量提升
带var的还是只声明,带function的老版本声明加提升,新版本浏览器(为迎合ES6块级作用域),只声明,不定义

console.log(a) //undefined
console.log(fn)  //undifined
if(1 == 2){
var a = 'test'
funciton fn(){
console.log('entry')
}
}
console.log(fn) // 函数本身
console.log(fn2) //undifined
if(1 == 1){
console.log(fn2) //函数体 条件成立,进入判断体后,先定义加声明
funcition fn2(){
console.log('fn2')
}
}

6、ES6中let和const不存在变量提升
7、堆栈内存的释放
堆内存:引用堆内存的变量赋值为null即可(没有变量占用这个堆内存,浏览器空闲时候会释放掉)
栈内存:一般情况下,函数执行完,所形成的私有作用域(栈内存)会自动释放掉,以下情况例外:
(1)函数执行完,形成的栈内存中内容被外界变量占用,此时栈内存不能被释放
(2)全局栈内存在页面关闭才会被释放

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: