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
的是申明 + 定义
let
和 var
的区别:
(1)区别 1:var
存在变量晋升,而 let
不存在
console.log(n); //=> undefined
console.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=12
console.log(n, window.n); //=> 12 12
window.n = 11;
console.log(n); //=> 11
let 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 defined
let 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); //=> 12
console.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 的区别
let
VSvar
:
1、var
存在变量晋升,而 let
不存在
2、在“全局执行上下文”中,基于 var
申明的变量,也相当于给 GO
(全局对象 window)新增一个属性,并且任何一个产生值的扭转,另外一个也会跟着变动(<u> 映射机制 </u>);然而,let
申明的变量,就是全局变量,与 GO
没有任何关系
3、在雷同上下文中,let
不容许反复申明【不论是基于何种形式申明的,只有申明过的,都不能基于 let
反复申明了】;而var
比拟涣散,反复申明也无所谓,反正浏览器也只会依照申明一次来解决的
4、暂时性死区:通过 typeof
检测时,前面有 let
申明的变量时,会报错的
5、let/const/function
会产生块级公有上下文,而 var
不会
– end –