[JavaScript]变量提升机制及ES6中的块级上下文

在“当前上下文”中,代码执行之前,浏览器首先会把所有带var/function关键字的进行提前声明或者定义:带var的只是提前声明 & 带function的,此阶段声明+定义{赋值}都完成了

  • let/const/import/class声明的变量不存在变量提升
  • 重复声明的问题
  • 推荐使用函数表达式,确保函数执行只能放在“创建函数”的下面,保证逻辑严谨性
  • 条件判断:在当前上下文中,变量提升阶段,不论条件是否成立,都要进行变量提升
    • var:还是只声明
    • function:判断体中的函数,在变量提升阶段,只声明不赋值「函数是个渣男」

真实项目中用函数表达式的方式把函数作为表达式赋值给变量,创建函数,这样抛开了变量提升的机制,导致函数的执行只能在创建函数代码之后保证逻辑的严谨性。

es6中的块级上下文

上下文:全局上下文、函数执行产生的私有上下文、ES6规范中新提供了“块级私有上下文”

块级私有上下文

除“函数和对象”的大括号外「例如:判断体/循环体/代码块…」,如果在大括号中出现了 let/const/function/class 等关键词声明变量,则当前大括号会产生一个“块级私有上下文”;它的上级上下文是所处的环境;var不产生,也不受块级上下文的影响;

  • 函数是个渣男
  • 循环中的块级上下文

script:VO(G) Global:GO BLOCK:块级作用域

变量提升:不论是否成立,都要进行变量提升,对于var来来讲新老版本没有任何影响,但是对于判断题中出现的function来讲新老版本表现不一致,老版本:函数声明+定义 新版本:函数只会声明不再定义

let和var的区别

1,let不存在变量提升,不允许在定义之前使用

js

console.log(a);//undefined
var a = 12;
console.lg(b);//Uncaught ReferenceError:Cannot access 'b'
before intialization

let b = 13;

2,let不允许重复声明「不论当前上下文中,基于何种方式声明过这个变量,都不允许基于let再次声明」 // Uncaught SyntaxError:Indentifier ‘a’has already been declared 在词法解析阶段,发现有基于let重复声明,词法解析就报错了,所以JS代码都不会执行。

3,在全局上下文中,基于var/function声明的变量,是给window(GO)设置的全局属性;基于let/const声明的变量是放在VO(G)中的,和GO没有任何关系;

js

var a = 12;
let b = 13;
console.log(a); //先看VO(G)中有没有,没有则继续看GO是否存在。。。12
console.log(window.a);//直接到GO中查找  12
console.log(b);//13
console.log(window.b);//undefined
console.log(c);//Uncaught ReferenceError: c is not defined
d = 100; //先看VO(G)中是否存在的,如果存在则修改全局变量值,如果不存在,则直接给GO设置d的属性(或者修改GO中的d的属性值)
console.log(window.d);//100

4,let会产生块级上下文

js

{
    var a = 12;// var不会产生块级上下文不受块级作用域的影响。
    let b = 13;// let会产生块级上下文
    console.log(a,b);12 13
}
console.log(a);//12
console.log(b);//Uncaught ReferenceError: b is not defined

5,let的暂时性死区问题:在词法解析阶段已经知道在用之后会存在这个变量定义定义之前使用它是不允许的 console.log(typeof a);//’undefined’ 检测一个未定义的变量会报undefined 基于typeof检测一个未被声明的变量,结果不会报错,而是“undefined”

console.log(typeof a);// Uncaught ReferenceError:Cannot access ‘a’ before intialization let a = 100;

let和const的区别

const声明的是常量,这句话是不准确的,他声明的函数变量;基于const声明的变量首先必须赋值初始值,而且一旦和某个值关联,后期不允许更改其指针指向(也就是不能重新赋值为其他的值)但是可以更改指针内容比如函数中的内容 const a;//Uncaught SyntaxError:Missing initializer in const declaration const a = 12; a = 13;//Uncaught TypeError:Assignment to constant variable. const obj = {name:’zj’}; obj.name = ‘zj1’ console.log(obj);//正常输出,所以不能说const定义常量

标签

发表评论