Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:很不错, 上课认真听了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>let的用法</title>
</head>
<body>
<!-- ul>li{item$}*5 -->
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
</ul>
<script>
// 1. let不支持重复声明,但是支持重复赋值
let str1 = "aaa";
// let str1 = "bbb";
// 上面这个行代码显示 “Identifier 'str1' has already been declared” 这样的报错,表示变量str1已经被使用,即不能重复声明
str1 = "bbb";
console.log(str1); // 输出:bbb
str1 = "ccc";
console.log(str1); // 输出:ccc
// 上面四行代码可以看出,是支持重复赋值的
/*====================================================================================================================*/
// 2. let不存在变量提升,无论是在全局作用域还是函数作用域
// console.log(str2);
// console.log(str2); 这行代码显示这样的报错:Cannot access 'str2' before initialization(不能在初始化以前使用str2)
// 说明在全局作用域下不存在变量声明的提升
let str2 = "hello";
console.log(str2); // 输出:hello
function demo() {
// console.log(str3); Cannot access 'str2' before initialization
let str3 = "world";
console.log(str3);
}
demo(); // 输出: world
// 从上面几行代码,也可以看出在函数作用域下也不支持变量声明提升
/*=====================================================================================================================*/
// 3. let支持块级作用域
if (true) {
let str4 = "didi";
console.log(str4); // 输出:didi
}
// console.log(str4); 输出:str4 is not defined
// 说明在if(){}这个代码块中,str4是有效的,但是在这个块级作用域以外就无效了
// let块级作用域示例
let lis = document.querySelectorAll("li");
for (var i = 0; i < lis.length; i++) {
lis[i].addEventListener("click", function () {
console.log("点击了 item" + (i + 1));
});
}
// 如果for()代码块中是用var声明的变量,最后不管你点击哪个item,都会出现item6,这就是var 不支持块作用域的原因,而且var声明会被提升
// 此案例中var声明会提升到全局,导致addEventListener这个代码块中的 i 不能共享到全局变量,当循环执行完以后,这个 i 就已经变成了 6
// 而let 就不一样,它支持块级作用域,所以每次循环的时候都会形成一个块级作用域,那么addEventListener这个代码块中的 i 就能得到其真实对应的值
for (let i = 0; i < lis.length; i++) {
lis[i].addEventListener("click", function () {
console.log("点击了 item" + (i + 1));
});
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>const的用法</title>
</head>
<body>
<script>
// const声明的是一种特殊变量(只读变量),就是所谓的常量
// 1. const声明的常量必须初始化
// const NAME;
// 报错信息:Missing initializer in const declaration (在const声明中缺少初始化)
const NAME = "jack";
console.log(NAME); // jack
/********************************************************************************************/
// 2. const 也不支持重复声明,并且不能重新赋值
// const NAME = "mike";
// 报错信息:Identifier 'NAME' has already been declared(变量NAME已经被使用了)
// NAME = "mike";
// console.log(NAME);
// 报错信息:Assignment to constant variable (常量类型的变量赋值出错)
/********************************************************************************************/
// 3. const 支持块级作用域
if (true) {
const GENDER = "male";
console.log(GENDER); // male
}
// console.log(GENDER); 报错: GENDER is not defined
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>let与const的区别</title>
</head>
<body>
<script>
// let与const的区别:
// 1. 相同之处:都不能重复声明,都支持块级作用域
// 2. 不同之处:let允许重新赋值(更新),而const禁止更新
// 实际开发中可能存在两种风格:
// 1. 全部都用const,除非这个数据后期会有改变
// 2. 可能会更新的或常用的都使用let,除非不会或不太可能被修改的才用const
// 基础上面两点总结:在开发中都尽量使用const会更加严谨,如果出现某个变量报错信息,修改它为let即可
// 有一些数据类型强烈推荐使用const,比如:对象或数组
// 1. 数组
const pics = ["image1", "image2", "image3"];
console.log(pics); // (3) ["image1", "image2", "image3"]
// 对数组中的元素进行增删改查也是没有问题的
pics.push("image4");
console.log(pics); // (4) ["image1", "image2", "image3", "image4"]
pics.splice(3, 2, "image5", "image6");
console.log(pics); // (5) ["image1", "image2", "image3", "image5", "image6"]
// 2. 对象
const obj = {
name: "jack",
age: 21,
email: "jack@qq.com",
};
console.log(obj.age); // 21
console.log(obj.name); // jack
obj.sex = "male";
console.log(obj.sex); // male
// 3. DOM操作时
const h1 = document.createElement("h1");
const body = document.querySelector("body");
h1.innerText = "标题";
h1.style.color = "red";
body.append(h1);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// 1. 数组示例:取出里面的元素分别赋值给变量
const arr = ["num1", "num2", "num3"];
// 传统做法
let num1 = arr[0];
let num2 = arr[1];
let num3 = arr[2];
console.log(num1, num2, num3); // num1 num2 num3
// 使用解构语法
let [n1, n2, n3] = arr;
console.log(n1, n2, n3); // num1 num2 num3
// 2. 对象示例:取出对象中的每个属性
const obj = {
name: "jack",
age: 20,
email: "jack@qq.com",
};
// 传统做法
let personName = obj.name;
let personAge = obj.age;
let personEmail = obj.email;
console.log(personName, personAge, personEmail); // jack 20 jack@qq.com
// 使用解构语法
let { name, age, email } = obj;
console.log(name, age, email); // jack 20 jack@qq.com
// 3. 在书写代码时,可能会直接使用解构语法为数组或对象赋值
let [p1, p2, p3] = ["pic1", "pic2", "pic3"];
console.log(p1, p2, p3); // pic1 pic2 pic3
// 注意点一:解构变量的声明必须初始化
// let [a, b, c];
// 报错信息:Missing initializer in destructuring declaration(解构声明中缺少初始值设定项)
let [a1, a2, a3] = [10, 20, 30];
console.log(a1 + a2 + a3); // 60
// 如果有值未初始化
let [b1, b2, b3] = [10, 20];
console.log(b1 + b2 + b3); // NAN
// 声明的同时赋上默认值
let [c1, c2, c3 = 50] = [10, 20];
console.log(c1 + c2 + c3); // 80
// 通过上面示例:可以理解成,此种书写方式下,左边看成是变量的声明,右边就是根据声明的变量为它赋值
// 注意点二:模板语法
// 解构数组使用 [] , 解构对象使用 {} ,一定要一一对应
// 在解构的过程中,是有两部分在参与,整个过程可以理解为一个解构表达式
// 1. 解构的源就是解构表达式的右边部分
// 2. 解构的目标就是解构表达式的左边部分
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>数组模型的解构</title>
</head>
<body>
<script>
const arr1 = ["name1", "name2", "name3"];
// 1. 解构所有元素
let [name1, name2, name3] = arr1;
console.log(name1, name2, name3); // name1 name2 name3
// 2. 解构部分元素,使用空占位符
let [n1, , n3] = arr1;
console.log(n1, n3); // name1 name3
// 3. 使用解构表达式更新变量
let num1 = 10;
let num2 = 20;
console.log(num1 + num2); // 30
[num1, num2] = [30, 40];
console.log(num1 + num2); // 70
// 4. 解构默认值
const arr2 = ["blue", "green", "yellow"];
let [c1, c2 = "black", c3] = arr2;
console.log(c1, c2, c3); // blue green yellow
let [d1, d2, d3, d4] = arr2;
console.log(d1, d2, d3, d4); // blue green yellow undefined
let [e1, e2, e3, e4 = "black"] = arr2;
console.log(e1, e2, e3, e4); // blue green yellow black
// 变量声明时使用默认值的话,如果数组中有对应的元素,那么会覆盖默认值,如果没有,那么会使用默认值
// 5. 嵌套解构
const arr3 = [1, 2, [3, 4], [[5, 6]], 7, 8];
// 取出所有数字
let [a1, a2, [a3, a4], [[a5, a6]], a7, a8] = arr3;
console.log(a1, a2, a3, a4, a5, a6, a7, a8); // 1 2 3 4 5 6 7 8
// 取出 5 和 6
let [, , [,], [[b5, b6]], ,] = arr3;
console.log(b5, b6); // 5 6
// 6. 函数参数中使用数组解构
function demo([x, y = 30]) {
return x + y;
}
console.log(demo([10, 20])); // 30
console.log(demo([10])); // 40
// 7. 剩余运算符解构
const arr4 = [10, 20, 30, 40, 50];
let [r1, ...r4] = arr4;
console.log(r1, r4); // 10 (4) [20, 30, 40, 50]
// 相当于把后面的参数解析成一个数组r4,let声明中的...r4,表示将数组r4展开,以便获取后面的所有元素,而r4就是保存这些元素的数组
// 8. 解构字符串
let str = " hello world ";
let [s1, s2, s3] = str;
console.log(s1, s2, s3); // h e 因为hello前面有一个空格,所以只得到 h e
let [, , , , , , ...ss] = str.trim(); // 将字符串两边空白去掉
console.log(ss); // (5) ["w", "o", "r", "l", "d"] 获得一个数组
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>对象模型的解构</title>
</head>
<body>
<script>
// 1. 基本解构
const obj1 = { num1: 10, num2: 30 };
let { num1, num2 } = obj1;
console.log(num1, num2); // 10 30
let { n1, n2 } = obj1;
console.log(n1, n2); // undefined undefined
// 解构对象时,变量的声明与对象中的属性名要一致,否则解析不了
// 2. 嵌套解构
const obj2 = {
name: "alice",
age: 20,
score: {
php: 80,
js: {
basis: 90,
advance: 78,
},
},
hobby: {
h1: "book",
h2: "run",
},
};
// 解析对象中的hobby
let { hobby } = obj2;
console.log(hobby); // {h1: "book", h2: "run"}
// 解析scroe-->js-->basis
let {
score: {
js: { basis },
},
} = obj2;
console.log(basis); // 90
// 按照模板将对应的属性名放入声明中就能很好的解析了,仔细一点就不会出错
// 3. 多次解构
// 解构出advance和h2
let {
score: {
js: { advance },
},
hobby: { h2 },
} = obj2;
console.log(advance, h2); // 78 "run"
// 4. 解构声明中可使用变量别名(解决不同对象中出现命名冲突的问题)
const obj3 = {
name: "jack",
age: 30,
};
let { name, age } = obj2; // alice 20
// let { name, age } = obj3; //Identifier 'name' has already been declared,如果变量名之前被使用过,现在就不能再使用了,所以要取别名
console.log(name, age);
let { name: objName, age: objAge } = obj3;
console.log(objName, objAge); // jack 30
// 5. 解构声明中可设置默认值
const obj4 = { a: "hello", b: "world", c: "yes" };
let { a, b, c = "嘿嘿" } = obj4;
console.log(a, b, c); // hello world yes 如果对象中存在对应的值,会覆盖默认值
let { a: obja, b: objb, c: objc, d = "no" } = obj4;
console.log(d); // no 如果对象中不存在对应的值,那么会使用声明中的默认值
// 6. 解构表达式更新变量
let s1 = 10;
let s2 = 20;
console.log(s1 + s2); // 30
({ s1, s2 } = { s1: 50, s2: 60 });
// 对象解构与数组解构的不同:1. 表达式右边要添加变量名 2. 表达式外层要套上一对小括号()
console.log(s1 + s2); // 110
// 7. 函数参数中使用对象解构
function show({ number1: x, number2: y }) {
console.log(x * y); // 50
y = 6;
console.log(x + y); // 11
}
show({ number1: 5, number2: 10 });
// 如果参数中有默认值,会优先使用参数的值
// 8. 解构剩余参数
const obj5 = {
personName: "tom",
personAge: 18,
personEmail: "tom@qq.com",
personHobby: "book",
};
let { personName, personAge, ...person } = obj5;
console.log(person); // {personEmail: "tom@qq.com", personHobby: "book"}
// 剩余参数会组成一个新的对象
</script>
</body>
</html>