思维导图 | 全面分析let和var的区别

公众号:朝霞的光影笔记ID:zhaoxiajingjing


公众号:朝霞的光影笔记ID:zhaoxiajingjing

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

变量提升:在当前上下文中,代码执行之前,会把所有var/function关键字的进行提前声明或者定义

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

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

letvar 的区别:

(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)新增一个属性,并且任何一个发生值的改变,另外一个也会跟着变化(映射机制);但是,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并且重复声明变量的操作,则直接报 语法错误Uncaught SyntaxError: Identifier 'n' has already been declared,整个代码都不会执行了

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

API:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone_and_errors_with_let

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/zh-CN/docs/Web/JavaScript/Reference/statements/block

API:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone_and_errors_with_let

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 是代码块所代表的块级上下文中 私有的

公众号:朝霞的光影笔记ID:zhaoxiajingjing

△ 图_debugger

② let 的闭包

浏览器的控制台并不能呈现很多东西,而是底层C++实现的

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

△ 形成了多少个块呢?

公众号:朝霞的光影笔记ID:zhaoxiajingjing

△图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)新增一个属性,并且任何一个发生值的改变,另外一个也会跟着变化(映射机制);但是,let声明的变量,就是全局变量,与GO没有任何关系

3、在相同上下文中,let不允许重复声明【不论是基于何种方式声明的,只要声明过的,都不能基于let重复声明了】;而var 比较松散,重复声明也无所谓,反正浏览器也只会按照声明一次来处理的

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

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

- end -

公众号:朝霞的光影笔记ID:zhaoxiajingjing

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值