0 / 能够申明变量的关键字

EC5:var/function

EC6:let/const/import

1 / let VS const

1、let 申明一个变量,变量存储的值能够扭转

2、const 申明的变量,一旦赋值,则不能再与其余值关联【不容许指针从新指向】

let n = 12;n =11;const m = 12; // Uncaught TypeError: Assignment to constant variable.【运行时谬误】m = 11;

△ 不能改

const obj = {    id:'zhaoxiajingjing'};obj.id = '晚霞的光影笔记';console.log(obj); //=> {id: "晚霞的光影笔记"}

△ const 不更改指针的指向即可

2 / let VS var

<u>变量晋升</u>:在以后上下文中,代码执行之前,会把所有var/function关键字的进行提前申明或者定义

(1)带var的只是提前申明

(2)带function的是申明+定义

letvar 的区别:

(1)区别1:var 存在变量晋升,而let不存在

console.log(n); //=> undefinedconsole.log(m); //=> Uncaught ReferenceError: m is not defined【运行时谬误】var n=12;let m=11;

△ var的变量晋升

(2)区别2:全局执行上下文的映射机制

在“全局执行上下文”中,基于var申明的变量,也相当于给GO(全局对象window)新增一个属性,并且任何一个产生值的扭转,另外一个也会跟着变动(<u>映射机制</u>);然而,let申明的变量,就是全局变量,与GO没有任何关系

① let VS var

var n = 12; // VO(G): var n=12 <=> GO:window.n=12console.log(n, window.n); //=> 12 12window.n = 11;console.log(n); //=> 11let m = 12;console.log(m, window.m); //=> 12 undefined

△ 映射机制

② 全局执行上下文中:不写var

x = 11; //=> window.x = 11; 没有写任何关键词申明,相当于给window设置一个属性console.log(x); //=> 先看看是不是全局变量,如果不是,再看看是不是window的一个属性console.log(y); //=> 两个都不是,那就报错,变量未定义 Uncaught ReferenceError: y is not defined【运行时谬误】

△ 不写var:在我的项目中尽量不要这样写

③ 函数中:不写var

function fn(){    /*    当函数执行时,这里造成公有上下文    遇到变量x时,依据【作用域链查找机制】    变量x找到全局都没有,    如果是设置值的操作,    则相当于给window设置一个属性    window.x = 11    */    x = 11; // window.x = 11    console.log(x); //11}fn();console.log(x);// 11

△ 不写var

function fn(){    /*    当函数执行时,这里造成公有上下文    当遇到变量y时,依据【作用域链查找机制】    变量y找到全局都没有,    如果获取的操作,    则间接报错,前面的代码就不执行了    */    x = 11;    console.log(y);// Uncaught ReferenceError: y is not defined【运行时谬误】}fn();console.log(x);

△ 不写var

(3)区别3:反复申明

在雷同上下文中,let不容许反复申明【不论是基于何种形式申明的,只有申明过的,都不能基于let反复申明了】;而var 比拟涣散,反复申明也无所谓,反正浏览器也只会依照申明一次来解决的

console.log('hello');var n = 11;let n = 12;

△ let 不容许反复申明

在代码执行之前,浏览器须要干很多活儿,比方:词法剖析,变量晋升

【词法分析阶段】如果发现有基于let/const并且反复申明变量的操作,则间接报 <u>语法错误Uncaught SyntaxError: Identifier 'n' has already been declared</u>,整个代码都不会执行了

(4)区别4:暂时性死区与typeof

API:https://developer.mozilla.org...

console.log(n); //=>Uncaught ReferenceError: n is not defined

△ 未被申明过的变量

console.log(typeof n); //=> undefined

△ 未被申明过的变量

console.log(typeof n); //=> Uncaught ReferenceError: n is not definedlet n;

△ let 没有变量晋升,在遇到申明之前是不能应用的

(5)区别5:块级作用域

let/const/function 会产生块级公有上下文,而var不会

① 上下文&作用域

哪些是,上下文 & 作用域:

1、全局上下文

2、函数执行造成的“公有上下文”

3、块级作用域(块级公有上下文),除了 对象/函数...的大括号之外的(例如:判断体、循环体、代码块)

API:https://developer.mozilla.org...

API:https://developer.mozilla.org...

while(1 !==1) {// 块级    }for(let i = 0; i<10; i++){// 块级    }if(1==1) {// 块级    }switch(1) { // 块级    case 1:        break;}switch(1) {     case 1:{// 块级         break;    }}{// 块级    }

△ 块级作用域/块级公有上下文

{    var n = 12;    console.log(n); //=> 12    let m = 11;    console.log(m); //=> 11}console.log(n); //=> 12console.log(m); //=>Uncaught ReferenceError: m is not defined

△ 块级作用域

n 是 全局上下文的:代码块不会对他有任何限度

m 是代码块所代表的块级上下文中 公有的

△ 图_debugger

② let 的闭包

浏览器的控制台并不能出现很多货色,而是底层C++实现的

for(let i = 0; i<5;i++) {    console.log(i);    i+=2;}

△ 造成了多少个块呢?

△图1_ 块级上下文

var buttons = document.querySelectorAll('button');// 浏览器在每一轮循环时,会帮咱们造成“闭包”for (let i = 0; i < buttons.length; i++) {    /*        let i = 0; 【父级块级上下文:管制循环】        i = 0 ;第一次 循环 公有块级上下文EC(B1)        => 以后上下文中,造成一个小函数,被全局的按钮的click占用了,        => EC(B1) 不会被开释掉        => 闭包    */    buttons[i].onclick = function () {        console.log(`以后按钮的索引:${i}`);    };}

△ let 的闭包

let i = 0; //=> 写在这里循环的时候,就不会产生块级上下文了for(; i < 5; i++){    console.log(i);}console.log(i);

3 / 小结:let和var的区别

letVSvar

1、var 存在变量晋升,而let不存在

2、在“全局执行上下文”中,基于var申明的变量,也相当于给GO(全局对象window)新增一个属性,并且任何一个产生值的扭转,另外一个也会跟着变动(<u>映射机制</u>);然而,let申明的变量,就是全局变量,与GO没有任何关系

3、在雷同上下文中,let不容许反复申明【不论是基于何种形式申明的,只有申明过的,都不能基于let反复申明了】;而var 比拟涣散,反复申明也无所谓,反正浏览器也只会依照申明一次来解决的

4、暂时性死区:通过typeof检测时,前面有let申明的变量时,会报错的

5、let/const/function 会产生块级公有上下文,而var不会

- end -