“这里是云端源想IT,帮你轻松学IT”
嗨~ 今天的你过得还好吗?
心要像伞一样
撑得起
收得住
- 2023.07.03 -
ECMAScript 6(ES6) 目前基本成为业界标准,它的普及速度比 ES5 要快很多,主要原因是现代浏览器对 ES6的支持相当迅速,尤其是 Chrome 和 Firefox 浏览器,已经支持 ES6 中绝大多数的特性。
所以,在我们学习前端开发时ES6也是必学的内容,今天小编就给大家详细讲解一下ES6的相关知识,赶快收藏起来慢慢学!
一、ES6简介
1.1、什么是ES6
ES6,全称 ECMAScript 6.0 ,是JavaScript 的当前版本标准。1995年美国netscape(网景)公司打造了一款主要用于check验证的脚本语言,而恰在此时,Sun公司的Java语言火的一塌糊涂,netscape公司为蹭其热度,便将该脚本语言命名为 JavaScript。
不料 JavaScript居然被越来越多的人使用,后效仿大秦的货币统一政策将其提交给国际标准组织ECMA。该组织发布的标准被称做ECMAScript。
2015年6月发布的版本称为ECMAScript2015,简称ES6。从ES6开始,该组织每年会发布一个版本,版本号比年份最后一位大1。
1.2、学前必知词汇
语法糖:又称糖衣语法,指不改变语言的本质功能,只是使编程变的更加简洁。而本课程后续所学习的很多ES6的新特性大多也都是由一粒粒语法糖所构成,所以ES6的一些新特性并不是真的“新”,只是试图简化语法而已。简言之:ES6是一大盒语法糖,解决了以前ES5很多难受的地方。
Babel:Babel是一个广泛使用的ES6转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。这意味着,你可以用ES6的方式编写程序,又不用担心现有环境是否支持。相信未来浏览器会逐渐对其提供原生的支持。
1.3、为什么要学习ES6
- ES5语言先天不足,通过学习ES6可以将其很多丑陋的部分进行隐藏。
- 包含了很多超棒的新特性,可以简化很多复杂的操作,从而大大提高开发效率。
- 为后面学习vue、react以及小程序做好充足准备。
- 目前大部分公司的项目都在使用ES6,它是前端发展的趋势,就业必备技能之一。
1.4 严格模式
ES5 除了正常运行模式(又称为混杂模式),还添加了第二种运行模式:“严格模式”(strict mode)。严格模式顾名思义,就是使 JavaScript 在更严格的语法条件下运行。
作用
- 消除 JavaScript 语法的一些不合理、不严谨之处,减少一些怪异行为;
- 消除代码运行的一些不安全之处,保证代码运行的安全;
- 为未来新版本的 JavaScript 做好铺垫。
使用
- 在全局或函数的第一条语句定义为: 'use strict';
- 如果浏览器不支持,只解析为一条简单的语句, 没有任何副作用。
语法和行为改变
- 必须用 var 声明变量,不允许使用未声明的变量
- 禁止自定义的函数中的 this 指向 window
- 创建 eval 作用域
- 对象不能有重名的属性(Chrome 已经修复了这个 Bug,IE 还会出现)
- 函数不能有重复的形参
- 新增一些保留字, 如: implements interface private protected public
- 使用call、apply传第一个参数为null或undefined时,this值不会跳转到全局对象
1.5 Object 扩展方法
var obj = {
name: "张阳",
age:18,
like:[
"早上跑步",
"晚上复习",
"人帅有腹肌"
]
}
Object.keys(obj)
遍历obj 对象中的键 (key)
Object.values(obj)
遍历obj 对象的值 (value)
Object.create()
Object.create 方法可以以**指定对象为原型创建新的对象,同时可以为新的对象**设置属性, 并对属性进行描述。
Object.create(proto, propertiesObject)
proto 指定的对象为原型
propertiesObject 设置新的属性
o2 = Object.create({}, {
p: {
value: 42,
writable: true,
enumerable: true,
configurable: true
}
});
- value : 指定值
- writable : 标识当前属性值是否是可修改的, 默认为 false
- configurable:标识当前属性是否可以被删除 默认为 false
- enumerable:标识当前属性是否能用for in 枚举 默认为 false
读写器
- get: 当获取当前属性时的回调函数
- set: 当设置当前属性时
Object.defineProperty(obj,“key”,{descriptors}) 只能写一个属性
get,set与value,writable不能同时存在
Object.defineProperty(obj,"age",{
value:18,
writable:true, //可编辑,默认为false
configurable:true,//可删除,默认为false
enumerable:true, //可遍历,默认为false
});
Object.defineProperty(obj,'name',{
get:function(){
return this._name || "今麦郎";
},
set:function(v){
this._name = v;
}
})
Object.defineProperties()
defineProperty复数形式:直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
Object.defineProperties(object, descriptors)
- object:要操作的对象
- descriptors:属性描述
get 作为该属性的 getter 函数,如果没有 getter 则为undefined。函数返回值将被用作属性的值。
set 作为属性的 setter 函数,如果没有 setter 则为undefined。函数将仅接受参数赋值给该属性的新值。
var obj2 = Object.defineProperties(obj,{
name:{
value:'老王'
},
age:{
value:18
},
like:{
get:function(){
// return _like || [];
// 如果不写return
// 默认return undefined;
},
set:function(v){
_like = v;
}
}
});
1.6 call、apply 和 bind
- call 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数;
- apply 方法调用一个具有给定 this 值的函数,以及作为一个数组(或类似数组对象)提供的参数;
- bind 同 call 相似,不过该方法会返回一个新的函数,而不会立即执行。
二、关键字扩展(重点)
2.1、let和块级作用域
2.1.1、ES5没有块级作用域
在ES5中,JS 的作用域分为全局作用域和局部作用域。通常是用函数区分的,函数内部属于局部作用域。
ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
- 内层变量可能会覆盖外层变量。
- 用来计数的循环变量泄露为全局变量。
2.1.2、块级作用域
在 ES6 中新增了块级作用域的概念,使用{}扩起来的区域叫做块级作用域。
- let关键字声明变量,实际上为 JavaScript 新增了块级作用域。
- 块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。
- 在块内使用let声明的变量,只会在当前的块内有效。
2.1.3、let关键字
ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效,也就是增加了块级作用域。
使用块级作用域(let定义的变量属于块级作用域) 防止全局变量污染。
- 块级作用域可以任意嵌套。
- for循环的计数器,就很合适使用let命令。
变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量。
你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
练习1:
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6]();
练习2:
```js
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6]();
2.1.4、let关键字特点
- let命令不存在变量提升
和var不同的还有,let命令不存在变量提升,所以声明前调用变量,都会报错,这就涉及到一个概念——暂时性死区。
暂时性死区即:区块中存在let或const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
- 不允许重复声明
let 只能声明一次而var 可以声明多次。
- 块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式不再必要了
- let 是在代码块内有效,var 是在全局范围内有效
- 不影响作用域链
let与var都拥有作用域链。
作用域链: 如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。
- 不再是顶层全局对象的属性
使用var定义的全局变量相当于直接挂载在window对象上, 而let不会。
2.2、const 关键字
变量:数据可以变化。在执行过程当中,有一些数据会使用多次,根据条件会变化,一般定义为变量。
常量:不会变化的数据,有些时候有的数据是不允许修改的,所以需要定义常量。
声明一定要赋初始值:一旦声明变量,就必须立即初始化,不能留到以后赋值。
const 声明一个只读变量,声明之后不允许改变。意味着,一旦声明必须初始化,否则会报错。
值不允许修改
const 其实保证的不是变量的值不变,而是保证变量指向的内存地址不允许改动。所以 使用 const 定义的对象或者数组,其实是可变的。
- const只在声明所在的块级作用域内有效。(与let相同)
- const命令声明的常量也是不会提升(与let相同)
- const不可重复声明(与let相同)
- 不再是顶层全局对象的属性(与let相同)
let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。
const使用的几点建议:
- 被多次使用且不允许更改的数据建议通过const定义;
- 项目全局常量建议大写,单词之间用-分隔;
- 如果不清楚要使用let还是const,那么就用const。如果后面发生值的改变,那么再将const改成let;
- 以后不允许使用var。
2.3 、块级作用域的函数声明
函数声明一般常用的是两种,一种是function声明,一种是函数表达式。
- 建议函数在顶层作用域和函数作用域之中声明,尽量避免在块级作用域声明。( "use strict"下报错)
- 如果确实需要,也应该写成函数表达式,而不是函数声明语句。
三、变量的解构赋值(重点)
3.1、什么是变量的解构赋值
解构 → 解析,重构。
- 解构的目标:数组以及对象。
- ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
- 解构赋值本质就是赋值:把结构解散重构然后赋值。
- 解构赋值是对赋值运算符=的一种扩展。
- 在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。
3.2、引入
在ES5中,开发者们为了从对象和数组中获取特定数据并赋值给变量,编写了许多看起来同质化的代码 。
3.3、解构赋值语法
解构的目标 = 解构源;(目标指的是定义的常量或变量,解析源一般指的是数组或对象)
解构目标:定义的常量或变量
解构源:待解构的数组或对象
3.4、对象解构赋值
对象解构赋值基本语法
对象的语法形式是在一个赋值操作符= 右边放置一个对象字面量
顺序不用一一对应
- = 右侧可以是一个常或变量
- 嵌套对象解构
解构嵌套对象仍然与对象字面量的语法相似,可以将对象拆解以获取想要的信息。
可忽略部分解构源的属性
剩余运算符
不完全解构:变量名称在对象中不存在
使用解构赋值表达式时,如果指定的变量名称在对象中不存在,那么这个变量会被赋值为undefined。
解构默认值(常用)
当指定的属性不存在时,可以定义一个默认值:在属性名称后添加一个等号(=)和相应的默认值即可。(为非同名局部变量赋值 ,可避免命名冲突)
如果希望使用不同命名的局部变量来存储对象属性的值,ES6中的一个扩展语法可以满足需求,这个语法与完整的对象字面量属性初始化程序的很像。
函数传参数:解构赋值表达式的值与表达式右侧(也就是=右侧)的值相等,如此一来,在任何可以使用值的地方都可以使用解构赋值表达式
3.5、数组解构赋值
基本使用
与对象解构的语法相比,数组解构就简单多了,它使用的是数组字面量,且解构操作全部在数组内完成,而不是像对象字面量语法一样使用对象的命名属性 。
忽略元素
在解构模式中,可以直接省略元素,只为感兴趣的元素提供变量名 。
- 变量交换
数组解构语法还有一个独特的用例:交换两个变量的值。在排序算法中,值交换是一个非常常见的操作,如果要在ES5中交换两个变量的值,则须引入第三个临时变量。
- 添加默认值
也可以在数组解构赋值表达式中为数组中的任意位置添加默认值,当指定位置的属性不存在或其值为undefined时使用默认值。
嵌套数组解构
嵌套数组解构与嵌套对象解构的语法类似,在原有的数组模式中插入另一个数组模式,即可将解构过程深入到下一个层级。
不定元素
函数具有不定参数,而在数组解构语法中有一个相似的概念——不定元素。在数组中,可以通过…语法将数组中的其余元素赋值给一个特定的变量。
数组复制
在ES5中,开发者们经常使用concat()方法来克隆数组。
3.6、混合解构(复杂解构)
混合使用对象解构和数组解构来创建更多复杂的表达式,可以从任何混杂着对象和数组的数据解构中提取想要的信息。
分享一个面试题:
//复杂解构
let wangfei = {
name: '王菲',
age: 18,
songs: ['红豆', '流年', '暧昧', '传奇'],
history: [
{name: '窦唯'},
{name: '李亚鹏'},
{name: '谢霆锋'}
]
};
// console.log(userName,age,one,two,three,four,name,name2,name3);// 王菲 18 红豆 流年 暧昧 传奇 窦唯 李亚鹏 谢霆锋
3.7、 解构传递参数
解构赋值可以应用在函数参数的传递过程中。
- 如果调用函数时不传入参数或设置默认值,被解构的参数会导致程序抛出错误;
- 可以为解构参数指定默认值。
3.8、解构返回结果
函数的多个返回值获取。
3.8、字符串解构
字符串也可以解构赋值。这是因为,字符串被转换成了一个类似数组的对象。
3.9、数值和布尔值解构
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
四、spread运算符与rest参数
在ES6中, 三个点(…) 有2个含义。分别表示扩展运算符(spread运算符) 和 剩余运算符(spread运算符)。
4.1、spread运算符
- 复制、合并数组
- 复制、合并对象
- 解构数组与对象
- 字符串转换为数组
- 伪数组转为真数组
4.2、rest参数
- rest 参数(形式为...变量名),rest运算符用于获取函数调用时传入的参数;
- 和普通参数混合使用的时候,需要放在参数的最后;
- 函数的length属性,不包括 rest 参数。
以上内容讲解了什么是ES6以及相关知识、let和块级作用域等关键字介绍、变量的解构赋值、spread运算符与rest参数的详细讲解,看到这里你已经对ES6相关知识点掌握了一半了,剩下的相关知识点我们下期接着讲解哦!
我们下期再见!
END
文案编辑|云端学长
文案配图|云端学长
内容由:云端源想分享