Skip to content

let 和 const 关键字与解构赋值(Day1 1/2) ​

本页对应 Day01_ES6,共 7 段视频,约 2 小时 16 分。

学习目标 ​

  1. 能说明 ES6 与 ES2015 的版本命名关系、ES6+ 的含义,以及 ECMAScript 与 JavaScript 的关系,并能解释 ES6 兼容性问题及 Babel 转译的作用。
  2. 能说明 ES5 严格模式的作用,列举严格模式下被禁止的典型语法(如八进制字面量、未声明变量直接赋值),并能在代码中识别和开启严格模式。
  3. 能对比 let 与 var 的四点区别(不能重复声明、不会提升、不作为全局对象属性、具有块级作用域),并针对每一点写出可运行的验证代码。
  4. 能说明 const 与 let 的区别(声明时必须初始化、值不可修改),能根据“是否需要重新赋值”正确选择 let 或 const,并能解释为什么 for 循环计数器通常使用 let。
  5. 能使用数组解构赋值完成多变量声明与赋值、交换两个变量的值、作为函数形参接收数组,并正确处理元素数量不一致和默认值的情况。
  6. 能解构嵌套数组及可迭代对象(字符串、arguments、元素集合),并能说明解构按索引/顺序匹配的规则,区分等号左侧是语法结构而非真正的数组。

知识点 ​

资料与定位 ​

本节开始进入 ES6+。先保留课堂给出的资料入口:官方地址 https://www.ecma-international.org/technical-committees/tc39/ ,铭哥教程 https://learn.fuming.site/front-end/es6/ ,阮一峰教程 https://es6.ruanyifeng.com/ 。为什么需要:ES6 新语法多,文档必须能随时查。怎么想:课堂教程为主,阮一峰教程作手册,学完某个点再对照查,不要一上来硬啃。怎么做:把链接收藏并整理到固定笔记目录。易错点:把“查文档”当成“系统学习”,遇到没学过的知识点就怀疑自己;转写稿也提醒,初学者看大部头教程有门槛,先跟课堂节奏。

ES6 与 ECMAScript 的关系 ​

为什么需要:后面天天说 ES6、ES2015,名称不统一会混乱。怎么想:ECMAScript 是正式名称,JavaScript 是俗称;ES6 的“6”是版本号,2015 年 6 月正式发布,正式名也叫 ES2015。之后每年发布新版本,所以“ES6”有时单指 ES2015,有时统称 2015 年后的新语法。怎么做:理解成“这门语言的新版本语法”,不要纠结“标准/实现”的文字游戏。易错点:以为每年都大更新;转写稿明确说 2015 年之后每年更新很少,主体仍是 ES2015。兼容性方面,老浏览器支持差,工程里常用 Babel 把 ES6 语法转成 ES5 写法,这是工程化的一环。

严格模式 ​

为什么需要:JS 早期有一些争议语法,严格模式让它们直接报错,逼开发者别用。怎么想:它不是新功能,是“补丁”;新人新办法,新代码按严格模式要求写。怎么做:在脚本开头写:

js
'use strict';

转写稿演示了两个典型:八进制 010 在严格模式下报错;未声明变量直接赋值也报错:

js
'use strict';
username = '张三'; // 报错:username is not defined

易错点:以为不写 'use strict' 就可以随便用;课堂要求即使不写,也别用严格模式禁止的写法。八进制前导 0 有争议,未声明变量自动创建全局变量也是垃圾语法,强烈不推荐。

let 创建变量 ​

为什么需要:var 有变量提升、无块级作用域、可重复声明等问题,容易出 bug。怎么想:把 let 当成更严谨的 var,重点记四个区别。怎么做:

js
let address = '上海';
// let address = '北京'; // 报错:不能重复声明
console.log(address); // 上海

四个特点:不能重复声明;不会提升,先使用后声明会报错;全局 let 变量不作为 window 属性;具备块级作用域。块级作用域可来自大括号、分支结构、循环结构。转写稿用 for 循环点按钮演示:var 时所有回调共用同一个 i,点谁都一样;换成 let 后,每次循环形成独立块,点谁拿到谁,不再需要闭包兜底。易错点:let 不是“完全替代 var 的万能药”,需要改值时仍可用 let;块级作用域外访问会报错。

const 创建变量 ​

为什么需要:很多变量创建后不应再改,语法层面禁止修改能减少错误。怎么想:const 也是创建变量,但值不能改,可称“常量”;JS 规范里仍属变量,只是值不可变。怎么做:

js
const schoolAddress = '北京';
// schoolAddress = '上海'; // 报错
// const a; // 报错:必须初始化

它同样具备 let 的四个特点:不能重复声明、不提升、不是 window 属性、有块级作用域。易错点:const 对象/数组内部属性可改,但变量指向不能改;转写稿强调“改变量的值”和“改对象属性”不是一回事。实际开发首选 const,发现要改再换 let。

数组解构赋值 ​

为什么需要:从数组里逐个取值给变量,传统写法啰嗦。怎么想:右边是真正的数组或可迭代对象,左边是“借数组结构写变量”的语法结构,按索引/顺序对应。怎么做:

js
const [v1, v2, v3] = [100, 200, 300];
console.log(v1, v2, v3); // 100 200 300

常见用法:交换变量 [v1, v2] = [v2, v1];函数传参 function fn([a, b, c]) {};数量不一致时多出的变量得 undefined;可给默认值 const [c1, c2, c3 = 250] = [100, 200];;嵌套数组按同样结构解;字符串、arguments、元素集合等可迭代对象也能解构。易错点:左边不是数组数据,只是结构;不能把左边存进变量再解构;默认值放前面通常没意义;不要因为学了新语法就忘了旧语法仍然生效。

为什么需要 let 和 const ​

ES6(正式版本也叫 ES2015)给 JavaScript 增加了新的变量声明方式:let 和 const。它们不是为了“多学一个关键字”,而是为了修补 var 留下的坑:var 可以重复声明、存在变量提升、没有块级作用域,写循环和事件回调时很容易出现“点击每个按钮都输出同一个值”的问题。严格模式下,八进制字面量、未声明变量直接赋值等“垃圾语法”会直接报错,这体现了同一思路:让语法层面尽早暴露错误。let 和 const 也是这个方向上的升级。

怎么想:把 let 当作 var 的替代品,但多了四个关键特点;把 const 当作“值不能改的变量声明”。现代浏览器和开发环境基本支持,学习时先按标准语法理解,不必一开始纠结旧浏览器兼容。

怎么做:以后声明变量优先考虑 const,确实需要重新赋值时再用 let,不要再用 var。

易错点:const 在 JS 中常被称为“常量”,但 JS 规范里并没有独立的“常量”类型;它本质仍是变量,只是值不能重新赋值。

let 特点一:不能重复声明 ​

为什么需要:var 在同一作用域重复声明不会报错,后写的会覆盖前面的,容易埋下隐蔽 bug。let 要求同一作用域内变量名唯一。

怎么想:先声明、后使用;同一个作用域里不要出现两个同名 let。

怎么做:

js
let address = '上海';
var a = 100;

// let address = '北京';
// 报错:Identifier 'address' has already been declared

var a = 200; // var 重复声明不报错

let 和 var 混用也不行:

js
let address = '上海';
var address = '北京'; // 报错

易错点:不是“换个关键字就能重复声明”。只要同一作用域已经用 let 声明过,再用 let 或 var 声明同名变量都会报错;不同块级作用域内可以同名。

let 特点二:不会提升,声明前不能访问 ​

为什么需要:var 的变量提升会让声明前的访问得到 undefined,看起来“有值但其实没赋值”。let 让变量在声明前不可访问,逼着我们先声明后使用。

怎么想:把“声明语句”当成变量真正生效的起点。

怎么做:

js
console.log(a); // undefined
var a = 100;

console.log(address); // ReferenceError
let address = '上海';

调试时会看到:var 输出 undefined,let 直接报“不能在初始化前访问/未定义”一类错误。这个报错不是坏事,它提前暴露了顺序问题。

易错点:不要以为 let 声明前访问会得到 undefined;它是报错。函数声明提升与 let 不是一回事,let 声明的函数表达式也不会提升。

let 特点三:全局变量不挂到 window ​

为什么需要:var 在全局声明的变量会成为 window 的属性,容易污染全局对象。let 声明的全局变量仍是全局作用域可访问,但不会成为 window 的属性。

怎么想:全局作用域和全局对象属性不是完全等号关系。

怎么做:

js
var a = 100;
let address = '上海';

console.log(window.a);       // 100
console.log(window.address); // undefined

易错点:window.address 得到 undefined 不会报错,因为访问对象不存在的属性返回 undefined;不要误以为 let 声明的变量不是全局变量。

let 特点四:块级作用域 ​

为什么需要:var 只看函数作用域,{}、if、for 里的变量会漏到外面,最典型的是循环事件回调共享同一个 i。

怎么想:let 除了保留全局作用域、函数作用域,还多了块级作用域:大括号、分支结构、循环结构都能形成块。

怎么做:

js
{
  var homeAddress = '上海';
  let schoolAddress = '北京';
}
console.log(homeAddress);   // 上海
console.log(schoolAddress); // ReferenceError

循环案例:

js
var liBooks = document.querySelectorAll('li');
for (var i = 0; i < liBooks.length; i++) {
  liBooks[i].onclick = function () {
    console.log(i);
  };
}

调试现象:点击每个 li 都输出循环结束后的同一个 i(例如 5)。因为 var i 不在块内独立,事件回调执行时循环早已结束。把 var 改成 let:

js
for (let i = 0; i < liBooks.length; i++) {
  liBooks[i].onclick = function () {
    console.log(i);
  };
}

每次迭代都有独立的块级 i,点击分别输出 0、1、2……不再需要为了这个场景额外写闭包。

易错点:let 不是抛弃函数作用域,而是升级:在函数里仍然是函数作用域,只是额外具备块级作用域;var 在块里仍然会漏到外层。

const:值不能改的变量声明 ​

为什么需要:有些变量声明后本来就不该改,比如获取到的元素、配置值。用 const 可以从语法层面杜绝误改,提高程序健壮性。

怎么想:const 具备 let 的四个特点:不能重复声明、不提升、全局不挂 window、有块级作用域;此外还多一条——值不能修改,且声明时必须初始化。

怎么做:

js
const schoolAddress = '北京';
// schoolAddress = '广州';
// 报错:Assignment to constant variable.

// const homeAddress;
// 报错:Missing initializer in const declaration

const 不能用于会改变循环变量的普通 for:

js
for (const i = 0; i <= 5; i++) {
  console.log(i); // 第一次后 i++ 报错
}

易错点:const 锁定的是“变量绑定”,不是对象内部属性。若变量指向对象,改对象属性不等于给变量重新赋值;但把变量指向另一个对象就会报错。常量名全大写只是其他语言的习惯,JS 不强制。实际开发优先 const,需要改值再换 let。

先明确:解构赋值到底在做什么 ​

为什么需要:当数组或对象里已经有一组值,我们又想把这些值分别交给多个变量时,传统写法要一个个取下标、一个个赋值,代码重复且容易看错位置。解构赋值就是为这种“拆开再分别赋值”的场景服务的。

怎么想:先把等号右边看成一个真正的数据来源,再把等号左边看成一个“变量摆放的结构”。右边是数组,左边也写成数组的样子,但左边不是数组数据,只是借数组的结构来放变量。

怎么做:本节笔记给的定义是:解构赋值是指按照一定模式,从数组和对象中提取值,对变量进行赋值,或函数传参。等号右边需要写数组或对象,可以是变量、直接量、表达式;等号左边要求把变量写在数组或对象结构中,并不是真正的数组或对象。

js
const arr = [100, 200, 300];
const [a, b, c] = arr;
console.log(a, b, c); // 100 200 300

易错点:不要把左边误认为“数组数据”。左边只是语法结构;右边才是真正参与取值的数组或对象。转写稿里反复强调:学了新语法,旧语法仍然生效,不能把 const vList = data 误解成“解构了左边结构”。

数组解构:按索引/顺序对上 ​

为什么需要:数组元素有顺序,我们经常要把第 1 个、第 2 个元素分别交给变量。解构让“取值并赋值”一行完成。

怎么想:转写稿里的推导是:左边变量在结构中的索引是 0,就去右边数组找索引 0 的元素;左边索引是 1,就找右边索引 1 的元素。可以简单记成“两边按索引对上”,更严谨地说,数组解构是按顺序匹配。

怎么做:

js
const [v1, v2, v3, v4, v5] = [100, 200, { name: '小乐', age: 100 }, function () { alert('ok'); }, Math.random()];
console.log(v1, v2, v3, v4, v5);

右边可以是直接量,也可以是变量:

js
const data = [100, 200, 300];
const [x, y, z] = data;

易错点:不要以为右边必须是“纯数组直接量”。变量、表达式只要结果是数组即可。左边变量名要符合变量命名规范,前面仍需用 const、let 等关键字声明。

数量不一致与默认值 ​

为什么需要:真实数据不一定和变量数量完全一致,可能多几个元素,也可能少几个元素。解构要能处理这种不齐的情况。

怎么想:右边多出来的元素没人接收就忽略;左边变量多出来而右边没有对应元素时,该变量得到 undefined。如果希望它不要是 undefined,可以给默认值。

怎么做:

js
const [a1, a2, a3] = [100, 200, 300, 400, 500];
console.log(a1, a2, a3); // 100 200 300

const [b1, b2, b3] = [100, 200];
console.log(b1, b2, b3); // 100 200 undefined

const [c1, c2, c3 = 250] = [100, 200];
console.log(c1, c2, c3); // 100 200 250

如果右边有第三个值,默认值会被覆盖:

js
const [d1, d2, d3 = 250] = [100, 200, 300];
console.log(d1, d2, d3); // 100 200 300

易错点:默认值一般放在后面才有意义。转写稿里说得很直接:按顺序赋值时,把默认值放前面“不报错但没意义”。另外,重新赋值时如果右边没有对应元素,变量会被赋成 undefined,不是保留原值。

交换变量、函数传参与复杂结构 ​

为什么需要:交换两个变量以前要引入第三方变量;函数接收一组参数时也常要把数组拆成多个形参。解构能让这些操作更直接。

怎么想:交换变量时,先构造右边的新数组 [v2, v1],再按位置赋回左边。函数传参本质上是“实参赋值给形参”,形参也是变量,所以可以用解构。

怎么做:

js
let v1 = '司马姥姥';
let v2 = '欧阳姥姥';
[v1, v2] = [v2, v1];
console.log(v1, v2); // 欧阳姥姥 司马姥姥

函数传参:

js
function fn([name1, name2, name3]) {
  console.log(name1 + '和' + name2 + '以及' + name3 + '是好朋友');
}
fn(['小明', '小刚', '小红']);

复杂结构也可以解,只要左边结构和右边对应:

js
const arr = [100, ['高小乐', 199], [1, 20]];
const [a, [b, c], [d, e]] = arr;
console.log(a, b, c, d, e);

同一个数组可以多种形式解构:

js
const [first, second, third] = arr;
console.log(first);  // 100
console.log(second); // ['高小乐', 199]
console.log(third);  // [1, 20]

易错点:嵌套解构时左边层级要和右边对应;交换变量时不要写成 v1 = v2; v2 = v1;,那样会丢失原值。函数形参看起来写了多个变量,但整体仍是一个参数位置上的数组结构。

类数组也能解构 ​

为什么需要:字符串、arguments、元素集合等“类数组”也有索引和长度,经常需要取出其中前几项。解构可以复用数组结构的写法。

怎么想:只要右边有可被按顺序取出的成员,就可以尝试用数组结构接收。转写稿提醒:更严谨的表述涉及“可迭代对象”,当前先按索引/顺序理解。

怎么做:

js
const msg = 'hello';
const [s1, s2, s3, s4] = msg;
console.log(s1, s2, s3, s4); // h e l l

const btns = document.querySelectorAll('button');
const [btn1, btn2, btn3] = btns;
console.log(btn1, btn2, btn3);

易错点:不要因为右边不是“纯数组”就不敢用;但也要知道解构不是万能的,核心仍是“按结构取值”。本节最稳的记忆是:右边是数据来源,左边是变量结构;数组解构按索引/顺序匹配;数量不齐时多则忽略、少则 undefined,需要时用默认值。

课堂画面 ​

课堂画面 1

课堂画面 2

课堂画面 3

课堂画面 4

课堂画面 5

课堂画面 6

代码示例 ​

示例一:let 与 const 及块级作用域 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>let 与 const</title>
</head>
<body>
  <ul>
    <li>第1项</li>
    <li>第2项</li>
    <li>第3项</li>
    <li>第4项</li>
    <li>第5项</li>
  </ul>

  <script>
    // 1. let 创建的变量不能重复声明,但可以修改值
    let address = '上海';
    // let address = '北京'; // 报错:Identifier 'address' has already been declared
    address = '广州';
    console.log(address); // 广州

    // 2. const 声明时必须给值,且值不能修改
    const schoolAddress = '北京';
    // schoolAddress = '上海'; // 报错:Assignment to constant variable
    // const workAddress;      // 报错:Missing initializer in const declaration

    // 3. let / const 都不提升
    // console.log(a); // 报错:Cannot access 'a' before initialization
    let a = 100;

    // 4. let 创建的全局变量不再是 window 的属性
    var b = 200;
    console.log(window.b);       // 200
    console.log(window.address); // undefined

    // 5. 块级作用域
    {
      var h01 = 100;
      let h02 = 200;
      console.log(h01, h02); // 100 200
    }
    console.log(h01); // 100
    // console.log(h02); // 报错:h02 is not defined

    // 6. for 循环产生块级作用域,不用闭包就能拿到各自的 i
    const lis = document.querySelectorAll('li');
    for (let i = 0; i < lis.length; i++) {
      lis[i].onclick = function () {
        console.log(i); // 点谁就是谁的下标
      };
    }
  </script>
</body>
</html>

要点解释与易错点

  • let 的四个特点:不能重复声明、不会提升、全局变量不是 window 的属性、多一个块级作用域;const 具备这四点,并且值不能修改、声明时必须给值。
  • 易错点:let 与 var 混用时,let address 之后再用 var address 也会报 already been declared,实际开发中别混着写。
  • 易错点:console.log(window.address) 不会报错,得到 undefined——使用一个不存在的属性只是 undefined,这与访问未声明变量不同。
  • 关键行:for (let i = 0; ...) 的 i 在每次迭代都是新的块级变量,所以回调里各自拿到 0、1、2……换成 var 就全是 5,必须靠闭包解决。
  • 大括号、分支结构(if、switch)、循环结构(for、while)都会产生块级作用域,但只对 let / const 声明的变量有效。

示例二:数组解构赋值基础 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>数组解构赋值</title>
</head>
<body>
  <script>
    // 1. 最基本形式:右边是真正的数组,左边是"数组结构"
    const arr = [100, 200, { name: '小乐', age: 100 }, function () { alert('ok'); }, Math.random()];
    const [v1, v2, v3, v4, v5] = arr;
    console.log(v1, v2, v3, v4, v5);

    // 2. 右边可以是变量、直接量、表达式
    let [a1, a2, a3] = [100, 200, 300];
    console.log(a1, a2, a3); // 100 200 300

    // 3. 交换两个变量的值,不需要第三方变量
    let vv1 = '司马姥姥';
    let vv2 = '欧阳姥姥';
    [vv1, vv2] = [vv2, vv1];
    console.log(vv1, vv2); // 欧阳姥姥 司马姥姥

    // 4. 用于函数传参(本质还是给形参赋值)
    function fn([name1, name2, name3]) {
      console.log(name1 + '和' + name2 + '以及' + name3 + '是好朋友');
    }
    fn(['小明', '小刚', '小红']);

    // 5. 两边结构不完全一致:变量多、元素少
    const [b1, b2, b3] = [100, 200];
    console.log(b1, b2, b3); // 100 200 undefined

    // 6. 默认值
    const [c1, c2, c3 = 250] = [100, 200];
    console.log(c1, c2, c3); // 100 200 250
  </script>
</body>
</html>

要点解释与易错点

  • 关键理解:等号右边是真正的数组数据(可以是变量、直接量、表达式),左边只是借用了数组的结构,里面写的是变量名,它不是数组类型的数据。
  • 易错点:let vList = [v1, v2, v3, v4]; 这种写法只是把四个变量的当前值取出来组成新数组,跟解构毫无关系,也不会回头修改 v1~v4。
  • 易错点:解构修改已有变量时,前面不能再加 let / const,加了就是重复声明;要修改值,变量本身必须是用 let 声明的(const 声明的不允许再赋值)。
  • 交换 [vv1, vv2] = [vv2, vv1] 是同步的,不存在"先改了 vv1 导致 vv2 也变了"的问题。
  • 默认值只对"右边取不到值(undefined)"时生效,并且带默认值的变量要放后面,放前面不报错但没有意义,因为赋值是按顺序/索引一一对应的。
  • 函数传参时形参写 [name1, name2, name3],说明这个函数其实只有一个参数(一个数组),别误以为写了三个参数。

示例三:嵌套数组解构与类数组解构 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>嵌套与类数组解构</title>
</head>
<body>
  <button>按钮1</button>
  <button>按钮2</button>
  <button>按钮3</button>

  <script>
    // 1. 嵌套(多维)数组解构:左边结构要和右边一致
    const arr = [100, ['高小乐', 199], [1, 20]];
    const [A, [B, C], [D, E]] = arr;
    console.log(A, B, C, D, E); // 100 高小乐 199 1 20

    // 2. 同一个数组可以多种形式解构
    const [F, G, H] = arr;
    console.log(F, G, H); // 100 ['高小乐', 199] [1, 20]

    // 3. 类数组也能解构:字符串
    const msg = 'hello';
    const [s1, s2, s3, s4] = msg;
    console.log(s1, s2, s3, s4); // h e l l

    // 4. 类数组也能解构:元素集合
    const btns = document.querySelectorAll('button');
    const [btn1, btn2, btn3] = btns;
    console.log(btn1, btn2, btn3);
  </script>
</body>
</html>

要点解释与易错点

  • 嵌套解构的关键:左边结构和右边结构一一对上,[A, [B, C], [D, E]] 中 B、C 在左边结构里的位置是"索引 1 里的 0 和 1",于是就从右边 ['高小乐', 199] 里取。
  • 关键行:const [F, G, H] = arr; 说明同一个数组可以被解构多次、用多种形式解构,G 拿到的是整个子数组,而不是被展开。
  • 类数组(字符串、arguments、querySelectorAll 得到的元素集合)也能解构,因为它们有索引、可以被遍历,成员按位置对应。
  • 易错点:元素多、变量少没关系(多的不管);变量多、元素少则对应位置得到 undefined,不会报错。
  • 易错点:解构取的是"位置/顺序",不是"名字"——变量名可以随便起,起名不影响取值结果。

常见错误 ​

  1. 现象:const price; 直接报错 → 原因:const 声明时必须初始化 → 修法:声明时给初值;若后续要重新赋值,改用 let。
  2. 现象:const count = 1; count = 2; 报错 → 原因:const 绑定不可重新赋值 → 修法:确需改值改 let,或重构为不可变数据。
  3. 现象:同一作用域写 let a; let a; 报错 → 原因:let/const 不允许重复声明 → 修法:改名、复用已有声明,或检查是否混用 var/let/const。
  4. 现象:{ const rate = 0.8; } console.log(rate); 报错 → 原因:块级作用域外访问 → 修法:在块内使用,或把声明移到需要访问的外层。
  5. 现象:for (const i = 0; i < 3; i++) 报错 → 原因:循环递增会重新赋值给 const → 修法:循环变量用 let。
  6. 现象:const list = [a, b]; const data = [1, 2]; list = data; 后 a/b 没变 → 原因:把左侧解构结构误当成可复用数组 → 修法:直接写 [a, b] = data;,左侧只是结构,不能存成变量再赋值。
  7. 现象:'use strict'; x = 1; 或 const n = 010; 报错 → 原因:严格模式禁止隐式全局变量和八进制旧写法 → 修法:先声明变量;八进制用 0o10 或十进制。

练习 ​

  1. 修复下面代码中的声明错误,保持原意,并标注每处报错类型:
js
const price;
let count = 1;
let count = 2;
{
  const rate = 0.8;
}
console.log(rate);
  1. 用数组解构完成三件事:交换 a 和 b;从 [100, [200, 300], 400] 中取出 100、200、300、400;给缺失项设置默认值 0。只写解构语句。

  2. 写函数 joinFriend([name1, name2, name3]),函数内用解构接收参数;分别用“数组直接量”和“已有数组变量”调用一次。

  3. 将字符串 "hello" 和页面按钮集合分别解构出前三个成员,并输出到控制台;要求写出获取按钮集合和解构的完整代码。

原视频对照 ​

#视频时长
1JS总结26:11
2ES介绍17:22
3ES5的严格模式04:47
4let关键字创建变量25:42
5const关键字创建变量15:10
6数组解构赋值0134:01
7数组解构赋值0213:14

小结 ​

  1. 默认先写 const,只有确实需要重新赋值时才降级为 let;这是本阶段代码审查的第一条。
  2. 遇到“重复声明、未定义、不能修改”三类报错,先查声明关键字、初始化时机和作用域边界。
  3. 解构赋值优先用于“从数组/对象中取值、交换变量、函数接收结构化参数”,不要为了用而用。
  4. 写循环绑定事件时,先用最小案例验证变量作用域,再放进项目代码。
  5. 严格模式下的限制要当作编码习惯,不要等浏览器报错才改。
  6. 新语法兼容性交给工程化工具处理,课堂和日常先按标准写法写,不混用 var/let/const。
  7. 练习时先手写预期输出,再运行对照;错误记录要包含“报错类型 + 触发语句 + 修复方式”。