第十一节:ES6解构赋值、var/let/const详解(作用域提升、windows关系、暂时性死区、使用场景等)
一. ES6解构赋值
1. 含义
允许按照一定模式,从数组和对象中提取值,对变量进行赋值的过程,叫做解构
2. 套路
(1). 符号:[]
(2). 别名:xx:别名
(3). 默认值: xx='默认值' 或 xx:别名='默认值'
(4). 剩余参数: ...xxx, 对象解构中是对象,数组解构中是数组
3. 数组的解构
全部解构、解构某个元素、剩余参数的使用、解构+默认值
代码分享:{ let nameArrays = ["ypf1", "ypf2", "ypf3"]; //全部解构 let [name1, name2, name3] = nameArrays; console.log(name1, name2, name3); //ypf1 ypf2 ypf3 //解构某一个元素 let [, , myName3] = nameArrays; //ypf3 console.log(myName3); //解构出来一个元素,剩下的放到数组里(形如剩余参数) let [item1, ...itemList] = nameArrays; console.log(item1, itemList); //ypf1 [ 'ypf2', 'ypf3' ] //解构的同时赋默认值 let [l1, l2, l3, l4 = "ypf4"] = nameArrays; console.log(l1, l2, l3, l4); //ypf1 ypf2 ypf3 ypf4 }
4. 对象的解构
全部解构、解构起别名、结构+默认值、解构+别名+默认值、剩余参数、复杂对象解构、函数中使用。
代码分享:

{ let obj = { name: "ypf", age: 18, height: 1.82, }; // 解构 let { name, age, height } = obj; console.log(name, age, height); // 解构并起别名 let { name: name1, age: age1, height: height1 } = obj; console.log(name1, age1, height1); // 解构+默认值,解构+别名+默认值 let { name2 = "ypf2", name: name3 = "ypf3" } = obj; console.log(name2, name3); //ypf2 ypf // rest剩余参数的使用 let { name: name4, ...restObj } = obj; console.log(name, restObj); //ypf { age: 18, height: 1.82 } // 复杂对象的解构 let options = { size: { width: 100, myheight: 200, }, items: ["Cake", "Donut"], extra: true, // something extra that we will not destruct }; let { size: { width, myheight }, items: [item1, item2], // assign items here title = "Menu", // not present in the object (default value is used) } = options; console.log(title); // Menu console.log(width); // 100 console.log(myheight); // 200 console.log(item1); // Cake console.log(item2); // Donut //函数中使用 function foo({ name, age }) { console.log(name, age); } foo(obj); //ypf 18 }
5. 字符串的解构
和数组解构类似
代码分享:
{ let str = "ypf001"; let [a, b, c, d, e] = str; console.log(a, b, c, d, e); //y p f 0 0 }
二. var/let/const详解
1. let 基本使用
(1). let 不允许声明同名变量(var可以)
(2). 其它声明变量方面和var没有太大区别
代码分享:
// 1.1 let 不允许声明同名变量 (下面代码报错) { let msg1 = "ypf1"; let msg1 = "ypf2"; } //1.2 var可以 { var msg2 = "ypf1"; var msg2 = "ypf2"; }
2. const基本使用
(1).const不允许声明重复变量
(2).const用来声明常量,保存的数据一旦被赋值,就不能被修改
特别注意:对于number、string、bool等数值类型不能直接修改,但是如果赋值的是引用类型,那么可以通过引用找到对应的对象,修改对象的内容。
【基本数据类型存储在 栈内存 中,引用数据类型存储在 堆内存 中然后在栈内存中保存 引用地址,对于引用类型而言,const 实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。】
(3). const声明变量的同时,必须赋值。
代码分享:
{ //2.1 const不允许声明同名变量(下面代码报错) { const msg1 = "ypf1"; const msg1 = "ypf2"; } // 2.2 声明的常量,对于基本数据类型不允许修改(下面代码报错) { const name1 = "ypf1"; name1 = "ypf2"; console.log(name1); //报错 Assignment to constant variable. } // 2.3 声明的常量,如果是引用类型,修改引用类型的地址,不允许;但是修改引用类型的值,是可以的 { const obj = { name: "ypf1", age: 20, }; obj.age = "30"; // 允许的,改的堆内存中的值,栈中的存放的地址没有修改 console.log(obj.age); obj = { name: "ypf2", }; // 不允许修改栈内存中存放的引用地址!! Assignment to constant variable. } //2.4 声明变量的同时必须赋值 { // const msg; //必须初始化 "const" 声明 } }
3. var、let/const到底有没有作用域提升呢?(也叫变量提升)
(1). 什么是作用域提升?
【答:在声明变量的作用域中,如果这个变量可以在声明之前被访问,那么我们可以称之为作用域提升】
(2). var是具有作用域提升的,如下例子,输出undefined,并没有报错,说明能访问。
(3). let、const没有进行作用域提升,但是会在“解析阶段”被创建出来
代码分享:
{ // 3.1 var是具有作用域提升的 { console.log(a); //undefined var a = "ypf"; } // 3.2 let/const创建的变量不能提前访问,所以不具有作用域提升功能 { console.log(msg1); //Cannot access 'msg1' before initialization let msg1 = "ypf"; console.log(msg2); //Cannot access 'msg2' before initialization const msg2 = "ypf"; } }
4. var、let/const和windows的关系 (需要在index.html页面测试)
(1). 全局通过var来声明一个变量,事实上会在window上添加一个属性
(2). let、const是不会给window上添加任何属性的
代码分享:
// 4.1 全局通过var来声明一个变量,事实上会在window上添加一个属性 { var msg1 = "ypf1"; console.log(window.msg1); //ypf1 } // 4.2 let/const不会给window上添加任何属性的 { let msg2 = "ypf2"; let msg3 = "ypf3"; console.log(window.msg2); //undefined console.log(window.msg3); //undefined }
5. 块级作用域
(1). 在之前的ES5中,没有块级作用域,只有函数作用域和全局作用域
(2). var 没有块级作用域,let/const/function/class声明的类型都是具有块级作用域的
注:不同的浏览器有不同实现的(大部分浏览器为了兼容以前的代码, 让function是没有块级作用域)
(3). if/switch/for 都是具有块级作用域的
(4). 块级作用域应用场景
有多个按钮,想给每个按钮添加一个事件,然后点击按钮依次输出每个按你对应的顺序,想要的结果是 0,1,2,3 如果直接用for循环+var,输出的结果永远是最大值,因为var是全局变量 这里引入两种解决方案,闭包和let块级作用域
代码分享:

{ // 5.4 if/switch/for 对应的块级作用域分析 // if { if (true) { var msg1 = "ypf1"; let msg2 = "ypf2"; const msg3 = "ypf3"; } console.log(msg1); //ypf1 console.log(msg2); //ReferenceError: msg2 is not defined console.log(msg3); //ReferenceError: msg3 is not defined } // switch { var color = "red"; switch (color) { case "red": var foo = "foo"; let bar = "bar"; } console.log(foo); //foo console.log(bar); //bar is not defined } // for(重点!!) { for (var i = 0; i < 3; i++) { console.log("循环内:" + i); // 0、1、2 } console.log("循环外:" + i); // 3 for (let i = 0; i < 3; i++) { console.log("循环内:" + i); // 0、1、2 } console.log("循环外:" + i); // ReferenceError: i is not defined } } // 块级作用域应用场景 { const btns = document.getElementsByTagName("button"); // 仔细理解!!!! // 参考博客:https://www.cnblogs.com/yaopengfei/p/14456993.html for (var i = 0; i < btns.length; i++) { btns[i].onclick = function () { console.log("第" + i + "个按钮被点击"); }; } // 方案1:采用闭包的方式解决 for (var i = 0; i < btns.length; i++) { (function (n) { btns[i].onclick = function () { console.log("第" + n + "个按钮被点击"); }; })(i); } // 方案2:直接使用let即可 for (let i = 0; i < btns.length; i++) { btns[i].onclick = function () { console.log("第" + i + "个按钮被点击"); }; } }
6. let/const具有暂时性死区
(1). 什么是暂时性死区?
【答:只要块级作用域内存在 let 命令,它所声明的变量就绑定在了这个区域,不再受外部的影响。】
(2). 案例如下
{ var a = 5; if (true) { a = 6; let a; } // Uncaught ReferenceError: Cannot access 'a' before initialization }
7. 补充
for (let i = 0; i < names.length; i++) 中不可以使用const声明变量
for (const item of names) 中可以使用const声明变量
8. 总结
(1). 对于var的使用:
我们需要明白一个事实,var所表现出来的特殊性:比如作用域提升、window全局对象、没有块级作用域等都是一些历史遗留问题;
其实是JavaScript在设计之初的一种语言缺陷;
但是在实际工作中,我们可以使用最新的规范来编写,也就是不再使用var来定义变量了;
(2). 对于let、const:
对于let和const来说,是目前开发中推荐使用的;
我们会有限推荐使用const,这样可以保证数据的安全性不会被随意的篡改;
只有当我们明确知道一个变量后续会需要被重新赋值时,这个时候再使用let;
这种在很多其他语言里面也都是一种约定俗成的规范,尽量我们也遵守这种规范;
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】