day31【stage01】
1 章节目录
1.1 目标
- 了解ECMAScript
- 掌握let关键字的使用
- 掌握const关键字的使用
- 掌握变量的解构赋值
- 掌握模板字符串
- 了解简化对象
1.2 重点
- 掌握let关键字的使用
- 掌握const关键字的使用
- 掌握变量的解构赋值
- 掌握模板字符串
1.3 难点
- 掌握变量的解构赋值
- 掌握模板字符串
2 ECMAScript 相关介绍
2.1. 什么是 ECMA
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-msmMuoqO-1676883909279)(MD%E6%96%87%E6%A1%A3.assets/clip_image002.jpg)]
ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制
造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1994 年后该 组织改名为 Ecma 国际。
2.2 什么是 ECMAScript
ECMAScript 是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言。
2.2 什么是 ECMA-262
Ecma 国际制定了许多标准,而 ECMA-262 只是其中的一个,所有标准列表查看
http 😕 / w w w.ecma- internation al.org / pu b lication s/stan d ard s/S tand ard .htm
2.3 ECMA-262 历史
第 1 版 | 1997 年 | 制定了语言的基本语法 |
---|---|---|
第 2 版 | 1998 年 | 较小改动 |
第 3 版 | 1999 年 | 引入正则、异常处理、格 式化输出等。IE 开始支持 |
第 4 版 | 2007 年 | 过于激进,未发布 |
第 5 版 | 2009 年 | 引入严格模式、JSON,扩 展对象、数组、原型、字 符串、日期方法 |
第 6 版 | 2015 年 | 模块化、面向对象语法、 Promise、箭头函数、let、 const、数组解构赋值等等 |
第 7 版 | 2016 年 | 幂运算符、数组扩展、 Async/await 关键字 |
第 8 版 | 2017 年 | Async/await、字符串扩展 |
第 9 版 | 2018 年 | 对象解构赋值、正则扩展 |
第 10 版 | 2019 年 | 扩展对象、数组方法 |
第 11 版 | 2020年 | 动态imports、BigInt、??操作符和?.操作符 |
注:从 ES6 开始,每年发布一个版本,版本号比年份最后一位大 1
2.4 谁在维护 ECMA-262
TC39(Technical Committee 39)是推进 ECMAScript 发展的委员会。其会员都是
公司(其中主要是浏览器厂商,有苹果、谷歌、微软、因特尔等)。TC39 定期 召开会议,会议由会员公司的代表与特邀专家出席
2.5 为什么要学习 ES6
⚫ ES6 的版本变动内容最多,具有里程碑意义
⚫ ES6 加入许多新的语法特性,编程实现更简单、高效
⚫ ES6 是前端发展趋势,就业必备技能
2.6 ES6兼容性
http://kangax.github.io/compat-table/es6 / 可查看兼容性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qGAeHhb1-1676883909279)(MD%E6%96%87%E6%A1%A3.assets/image-20220809235017249.png)]
目前主流浏览器都支持ES6的新特性。
3 let 关键字
let 关键字用来声明变量,使用 let 声明的变量有几个特点:
-
不允许重复声明
-
块儿级作用域
-
不存在变量提升
-
不影响作用域链
应用场景:以后声明变量使用 let 就对了
3.1 let创建变量代码示例
let a;
let b,c,d;
let e = 100;
let f = 521, g = 'iloveyou', h = [];
3.2 不允许重复声明
//变量不能重复声明
// let star = '周杰伦';
// let star = '周董';
//报错 Uncaught SyntaxError: Identifier 'star' has already been
3.3 块儿级作用域(局部变量)
// 块儿级作用域(局部变量);
{
let cat = "猫";
console.log(cat);
}
console.log(cat);
// 报错:Uncaught ReferenceError: cat is not defined
}
3.4 不存在变量提升
什么是变量提升:
就是在变量创建之前使用(比如输出:输出的是默认值),let不存在,var存在
// 不存在变量提升;
// 什么是变量提升:就是在变量创建之前使用(比如输出:输出的是默认值),let不存在,var存在;
console.log(people1); // 可输出默认值
console.log(people2); // 报错:Uncaught ReferenceError: people2 is no
defined var people1 = "大哥"; // 存在变量提升
let people2 = "二哥"; // 不存在变量提升
3.5 不影响作用域链
// 不影响作用域链;
// 什么是作用域链:很简单,就是代码块内有代码块,跟常规编程语言一样,上级代码块中
的局部变量下级可用
{
let p = "大哥";
function fn(){
console.log(p); // 这里是可以使用的
}
fn();
}
3.6 let案例:点击div更改颜色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>点击 DIV 换色</title>
<link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css"
rel="stylesheet">
<style>
.item {
width: 100px;
height: 50px;
border: solid 1px rgb(42, 156, 156);
float: left;
margin-right: 10px;
}
</style>
</head>
<body>
<div class="container">
<h2 class="page-header">点击切换颜色</h2>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script>
//获取div元素对象
let items = document.getElementsByClassName('item');
//遍历并绑定事件
for(let i = 0;i<items.length;i++){
items[i].onclick = function(){
//修改当前元素的背景颜色
// this.style.background = 'pink';
//如果使用var 此时变量i会出现下标越界 从而无法实现效果
items[i].style.background = 'pink';
}
}
</script>
</body>
</html>
效果如图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rco40DAW-1676883909280)(MD%E6%96%87%E6%A1%A3.assets/image-20220810001043456.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wFiWlRWf-1676883909280)(MD%E6%96%87%E6%A1%A3.assets/image-20220810001106044.png)]
4 const 关键字
const 关键字用来声明常量,const 声明有以下特点
-
声明必须赋初始值
-
标识符一般为大写
-
不允许重复声明
-
值不允许修改
-
块儿级作用域
注意: 对象属性修改和数组元素变化不会出发 const 错误 应用场景:声明对象类型使用 const,非对象类型声明选择 let
//1. 一定要赋初始值
// const A;
//2. 一般常量使用大写(潜规则)
// const a = 100;
//3. 常量的值不能修改
// SCHOOL = 'ATGUIGU';
//4. 块儿级作用域
// {
// const PLAYER = 'UZI';
// }
// console.log(PLAYER);
//5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
const TEAM = ['UZI','MXLG','Ming','Letme'];
// TEAM.push('Meiko');
5 变量的解构赋值
5.1 基本用法
ES6 允许按照一定模式从数组和对象中提取数据,对变量进行赋值,这被称为解构,只要等号两边的模式相同,左边的变量就会被赋予对应的值。本质上,这种写法属于模式匹配
let [a,b,c] = [1,2,3]
//等同于
let a = 1
let b = 2
let c = 3
let [foo, [[bar], baz]] = [1, [[2], 3]
// foo 1
// bar 2
// baz 3
如果解构不成功,变量的值就等于undefined
let [foo] = [] //解构不成功 undefined
let [bar, foo] = [1] //解构不成功 undefined
5.2 默认值
解构赋值允许指定默认值
let [foo = true] = []
console.log(foo) //true
ES6内部使用严格模式相等运算符(===),判断一个位置是否有值,当一个数组成员严格等于undefined,默认值才会生效
let [x = 1] = [undefined]
console.log(x) //1
let [x = 1] = [null]
console.log(x) //null
如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候才会求值
function fn(){
return 2
}
let [x = fn()] = [1]
console.log(x) // 1, 因为x能取到值,所以函数fn根本不会执行,只有当x取不到值的时候fn才会执行
默认只可以引用解构赋值的其它变量,但该变量必须已经声明
let [x = 1, y = x] = [] //x=1,y=1
let [x = 1, y = x] = [2] //x = 2,y = 2
let [x = 1, y = x] = [1,2] //x = 1,y = 2
let [x = y, y = 1] = [] //报错,因为在给x赋值为y时,y还没有声明
5.3对象解构
基本用法
数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值
let {foo,bar} = {foo: 'aaa', bar: 'bbb'}
//foo aaa
//bar bbb
let obj = {
p: [
'hello',
{y: 'world'}
]
}
let {p,p:[x,{y}]} = obj
x //'hello'
y //'world'
p //["hello",{y: 'world'}]
如果解构失败,变量的值等于undefined
let {foo} = {bar: 'baz'}
// foo undefined
如果变量名与属性名不一致,必须写成下面这样
let {foo: baz} = {foo: 'aaa', bar: 'bbb'}
//baz 'aaa'
这实际上说明,对象的解构赋值是下面形式的简写
let {foo: foo, bar: bar} = {foo: 'aaa',bar: 'bbb'}
也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者
默认值
对象也可以指定默认值
var {x = 3} = {}
//x 3
var {x, y=5} = {x: 1}
//x 1,y 5
默认值生效的条件是,对象的属性值严格等于undefined
var {x = 3} = {x: undefined}
// x 3
var {x = 3} = {x: null}
//x null
注意点
(1)如果将一个已经声明的变量用于解构赋值,必须非常小心
//错误写法
let x
{x} = {x: 1}
这里会报错,因为JavaScript引擎会将{x}理解成一个代码块,从而发生词法错误。只有不将大括号写在行首,避免JavaScript将其解释为代码块,才能解决这个问题。
//正确写法
let x
({x} = {x: 1})
(2)解构赋值允许左边的模式之中,不放置任何变量名。
({} = [true,false])
({} = 'abc')
({} = [])
上面表达式虽然毫无意义,但是语法是合法的,可以执行
(3)由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构
let arr = [1,2,3]
let {0: first,[arr.length - 1]: last} = arr
first //1
last //3
上面代码对数组进行对象结构。数组arr的0键对应的值是1,[arr.length - 1]就是2键,对应的值是3。方括号这种写法,属于属性名表达式
5.4 字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类数组的对象
const [a,b,c,d,e] = 'hello'
a //'h'
b //'e'
c //'l'
d //'l'
e //'o'
ES6数组与对象的解构赋值详解
pdf 0星 超过10%的资源 53KB
下载
类数组的对象都有一个length属性,因此还可以对这个属性解构赋值
let {length: len} = 'hello'
len //5
5.5 数值和布尔值的解构赋值
解构赋值时,如果等号右边是数组和布尔值,则会先转为对象
let {toString: s} = 123
s === Number.prorotype.toString //true todo:待验证
let {toString: s} = true
s === Boolean.prototype.toString //true
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对他们进行解构赋值都会报错
let {prop: x} = undefined //报错
let {prop: y} = null //报错
5.6 函数参数的解构赋值
function add([x,y]){
return x + y
}
add([2,3]) //5
[[1,2],[3,4]].map(([a,b])=>a + b)
//[3,7]
函数add的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量x和·y。对于函数内部代码来说,他们能感受到的参数就是x和y。
函数参数的解构也可以使用默认值
function move({x = 0,y = 0} = {}){
return [x, y];
}
move({x: 3, y: 8}) //[3,8]
move([x: 3]) //[3, 0]
move({}) //[0,0]
move() //[0,0]
5.7 圆括号问题
解构赋值虽然很方便,但是解析起来并不容易。对于编译器来说,一个式子到底是模式还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能知道。
由此带来的问题是,如果模式中出现圆括号怎么处理。ES6的规则是,只要有可能导致结构的歧义,就不得使用圆括号。
不能使用圆括号的情况
(1)变量声明
//全部报错
let [(a)] = [1]
let {x: (c)} = {}
let ({x: c}) = {}
let {(x: c)} = {}
let {(x): c} = {}
let {o: ({p: p}) } = { o: {p: 2} }
上面6个语句都会报错,因为他们都是变量声明语句,模式不能使用圆括号
(2)函数参数
函数参数也属于变量声明,因此不能带有圆括号
//全部报错
function fn([(2)]){
return z
}
function fn2([z,(x)]){
return x
}
(3)赋值语句的模式
使用不同的方法结合/合并两个JS数组
pdf 0星 超过10%的资源 57KB
下载
//全部报错
({ p: a}) = { p: 42 }
([a]) = [5]
[({p: a }), {x: c}] = [{}, {}]
上面代码将整个模式或部分模式放在圆括号之中,导致报错
可以使用圆括号的情况
可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号
[(b)] = [30]
({p: (d)} = {})
[(parseInt.prop)] = [3]
上面三行语句都可以正确执行,因为首先它们都是赋值语句,而不是声明语句;其次它们的圆括号都不属于模式的一部分。第一行语句中,模式是取数组的第一个成员,跟圆括号无关;第二行语句中,模式是p,而不是d;第三行语句与第一行语句的性质一致。
5.8 用途
(1)交换变量的值
let x = 1
let y = 2
[x,y] = [y,x]
(2)从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能将他们放在数组或对象里返回,有了解构赋值,取出这些值就非常方便。
//返回一个数组
function fn(){
return [1,2,3]
}
let [a,b,c] = fn()
//返回一个对象
function fn2(){
return {
name: 'zhangsan',
age: 18
}
}
let {name,age} = fn2()
(3)函数参数的定义
解构赋值可以方便的将一组参数与变量名对应起来
//参数是一组有次序的值
function fn([x,y,z]){
...
}
fn([1,2,3])
// 参数是一组无次序的值
function fn2({x,y,z}){
...
}
fn2({z:3,y:2,x:1})
(4)提取JSON数据
解构赋值对提取JSON对象中数据非常有用
let jsonData = {
id: 42,
status: 'ok',
data: [20,30]
}
let {id,status,data:number} = jsonData
console.log(id,status,number)
//42,'ok',[20,30]
(5)参数的默认值
function fn([a=10,b=20]){
return a+b
}
fn() //30
fn(1,2) //3
(6)遍历Map解构
任何部署了Iterator接口的对象,都可以用for…of循环遍历。Map结构原生支持Iterator接口,配合变量的解构赋值,获取键名和键值就非常方便
const map = new Map()
map.set('first','hello')
map.set('second','word')
for(let [key, value] of map){
console.log(key + "is" + value)
}
(7)输入模块的指定方法
const {SourceMapConsumer, SourceNode} = require("source-map")
6 模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
-
字符串中可以出现换行符
-
可以使用 ${xxx} 形式输出变量
const username1 = 'alex';
const username2 = `alex`;
console.log(username1, username2, username1 === username2);
模板字符串与一般字符串的区别
const person = {
username: 'Alex',
age: 18,
sex: 'male'
};
一般字符串:
const info =
'我的名字是:' +
person.username +
', 性别:' +
person.sex +
', 今年' +
person.age +
'岁了';
console.log(info);
//我的名字是Alex,性别:male,今年18岁了
模板字符串:
const info = `我的名字是:${person.username}, 性别:${person.sex}, 今年${person.age}岁了`;
console.log(info);
//我的名字是Alex,性别:male,今年18岁了
注意:
1.和其他东西一起使用的时候,使用模板字符串,方便注入
2.其他情况下使用模板字符串或一般字符串都行
三、模板字符串的注意事项
1、输出多行字符串
一般字符串:
const info = '第1行\n第2行';
// console.log(info);
模板字符串:
法一:
const info = `第1行\n第2行`;
法二:
const info = `第1行
第2行`; //这里前边有空格
2.输出 ` 和 \ 等特殊字符
const info = `\`\\`; //需要转义
console.log(info); //`\
一般字符:不需要转义
const info = `'`;
console.log(info); //'
3.模板字符串的注入
const username = 'alex';
const person = { age: 18, sex: 'male' };
const getSex = function (sex) {
return sex === 'male' ? '男' : '女';
};
const info = `${username}, ${person.age},${getSex(person.sex)}`;
console.log(info);
结论:只要最终可以得出一个值的就可以通过 ${} 注入到模板字符串中
7 简化对象写法
ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
<!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>
//ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
//这样的书写更加简洁
let name = 'HOPEIT';
let change = function(){
console.log('我们可以改变你!!');
}
const school = {
name,
change,
improve(){
console.log("我们可以提高你的技能");
}
}
console.log(school);
</script>
</body>
</html>
7 章节总结
- 了解ECMAScript
- let关键字的使用
- const关键字的使用
- 变量的解构赋值
- 模板字符串
- 简化对象写法
YPE html>
7 章节总结
- 了解ECMAScript
- let关键字的使用
- const关键字的使用
- 变量的解构赋值
- 模板字符串
- 简化对象写法