1.什么是ES6
ES6即ECMA Script, 是由ECMA国际标准化组织,制定的一项脚本语言的标准化规定。
ES6很多时候是一个泛指,指在ESMA Script 2015之后的版本。
2. let声明变量
ES6中新增的用于声明变量的关键字。
1.let 声明变量只在所处的块级有效
if (true) {
// let声明有块级作用域的概念 而var没有这方面的概念
let a = 0
var b = 0
}
console.log(b)// 0
console.log(a)//a is not defined(报错) 因为块级作用域外界无法访问
2.let 不存在变量的提升
console.log(a) //undefined
var a = 20
因为var在预编译时会将声明提前
最终编译为
var a
console.log(a)
a=0
所以打印是undefined
而下面的let不存在变量提升
console.log(b)//报错
let b = 20
3.暂时性死区
因为自己作用域的let无法提前,外部又访问不到,这就形成了暂时性死区。
var a= 123
if(true){
a=456 //因为自己的作用域中的let无法提前,外部又访问不到
let a
}
3. const声明常量
作用:声明常量
常量:常量就是值(内存地址)不能变化的量
1.const常量赋值后,值不能更改
const p =3.14
p=100 //报错
2.当const 声明复杂类型时,可以修改其中的项,但不能给整个常量重新赋值,改变其内存地址
const arr = [100,200]
arr[0]=400,
arr[1]=[500]
console.log(arr) // 400,500
arr=[699,799]
console.log(arr)//报错
let 、const、var 的区别
var | let | const |
---|---|---|
函数级作用域 | 块级作用域 | 块级作用域 |
声明变量 | 声明变量 | 声明常量 |
变量提升 | 不存在变量提升 | 不存在变量提升 |
值可更改 | 值可更改 | 值不可改(复杂类型内存地址不可改) |
允许重复声明 | 不允许重复声明 | 不允许重复声明 |
4. 解构赋值
ES6中允许从数组或对象中提取值,按照对应位置,对变量赋值,这就是解构赋值。
1.数组结构赋值
const arr = ["沈腾", "贾玲", "关晓彤", "华晨宇"]
let {user1,user2,user3,user4,user5} =arr
//结构数值一一对应 结构不成功,则该值为undefined
console.log(user1) //沈腾
console.log(user2)//贾玲
console.log(user3)//关晓彤
console.log(user4)//华晨宇
console.log(user5)//undefined
2.对象解构赋值
let person={name:"憨八龟",age:38}
//对象结构赋值有两种方法
写法一: 直接使用
let {name,age}=person
console.log(name)//憨八龟
console.log(age)// 18
写法二:let {name:youName,age=youAge} =person
console.log(youName)//憨八龟
5. 模板字符串
ES6新增创建字符串的方式,使用反引号定义。
1.模板字符串通过${}可以解析变量
let name = `张三`
let say=`hello,${name}
,你好吗`
2.模板字符串中可以调用函数
3.模板字符串中可以换行
6.对象的自增强写法
1.对象的属性和值相同 则可以省略
let obj={
//name:name 可以简写为
name
}
2.方法简写
let obj ={
//fn:function(){}可以简写为
fn(){}
}
7. 箭头函数
ES6中定义函数的方式。
ES5定义函数的方式
function sum (num){
console.log(num)
}
ES6中定义函数的方式
//当参数只有一个时 可以省略小括号
//当函数体只有一句话 且代码结果就是返回值时,可以省略大括号
//函数体只有一行时,如果要return结果 则必须不写return
const sum =num=>console.log(num)
1.箭头函数不绑定this,其this指向函数定义位置上下文的this
2.不能作为构造函数 实例化对象
let person =(name){
person.name = name
}
let user = new person("憨八龟")
console.log(user) //报错
3.不能使用arguments函数
let fn(){
console.log(arguments) //报错
}
fn(1,2,3)
箭头函数的适用场景:
箭头函数适合与this无关的回调,如定时器,数组的方法回调等。
箭头函数不适合与this有关的回调,事件回调,对象的方法。
8. 函数的初始默认值
ES6中允许函数有默认初始值。
//与解构赋值搭配
function request({
name = "憨八龟",
age = 19
}) {
console.log(name) //忍者神龟
console.log(age) //18
}
request({
name: "忍者神龟"
})
9. rest参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments,并转而用数组的方式输出,加强对数据的处理。
ES5
function content() {
console.log(arguments);//结果是一个对象
}
content(1, 2, 3, 4)
ES6
function content(a, b, ...args) {
console.log(args)//结果是一个数组[3,4]
}
content(1, 2, 3, 4)
10.扩展运算符
1.扩展运算符可以将对象或数组转为用逗号隔开的参数序列。
格式为:…要展开的对象或数组
let arr = [1,2,3]
console.log(...arr) //1 ,2 ,3
console.log(arr) //[1,2,3]
2.扩展运算符可以应用于合并数组
let arr =[1,2,3]
let arr2 = [4,5,6]
let arr3=[...arr,...arr2]
console.log(arr3) //1,2,3,4,5,6
3.将伪数组或可遍历的对象转换为真正的数组
let divs = document.getElementByName('div')
divs =[...divs]
11. Symbol数据类型
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
注意
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其他数据进行运算
- Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用 Reflect.ownKeys 来获取对象的所有键名.
1.创建symbol
let s1= symbol()
2.symbol函数可以接收一个字符串作为参数,
//该字符串表示对symbol实例的描述,主要用于区分
let s2=Symbol("user")
//可以转字符串
String(s2)或 S2.toString
//可以转布尔类型
!S2
3.作为属性名的 Symbol
//由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。 --来自阮一峰老师ES6
let mySymbol = Symbol();
// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';
// 第二种写法
let a = {
[mySymbol]: 'Hello!'
};
// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
//注意,Symbol 值作为对象属性名时,不能用点运算符。
// 以上写法都得到同样结果
a[mySymbol] // "Hello!"
4. symbol.for()全局注册方法
有时,我们希望重新使用同一个 Symbol 值,Symbol.for()
方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。
Symbol()每调用一次 创建一个不同的Symbol对象
let arr1 = Symbol("arr")
let arr2 = Symbol("arr")
console.log(arr1 == arr2) //false
Symbol.from 全局注册,调用时现在全局找 全局有则使用 没有的话再创建Symbol对象
let arr3 = Symbol.for("arr")
let arr4 = Symbol.for("arr")
console.log(arr3 == arr4) //true
symbol很多情况下是对对象的扩展
let demo = {
name: "我是demo",
[Symbol("hi")]() {
console.log("你好吗")
},
[Symbol("superman")]() {
console.log("我是超人")
}
}
demo[Symbol("age")] = () => {
console.log("我今年199岁了")
}
console.log(demo)
效果图:
5.获取symbol的字符串描述.description
let demo = Symbol ("你好啊")
console.log(demo.description) //你好啊
12.迭代器(for…of)
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提 供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。Iterator接口在JS指的是其属性Symbol(Symbol.iterator)。例如数组的Symbol(Symbol.iterator)属性在其原型链上。
注意: 需要自定义遍历数据的时候,要想到迭代器。
原生具备 iterator 接口的数据(可用 for of 遍历):
- Array
- Arguments
- map
- set
- String
- TypedArray
- NodeList
迭代器工作原理:
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
- 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
- 每调用 next 方法返回一个包含 value 和 done 属性的对象
自定义遍历数据,手动写迭代器
let obj = {
user: "管理员",
jurisdiction: ["增", "删", "改", "查"],
// obj是对象没有Symbol.iterator属性 所以自己创建
[Symbol.iterator]() {
let index = 0;
return {
// 手动创建next方法
next: () => {
if (index < this.jurisdiction.length) {
let result = {
value: this.jurisdiction[index],
done: false
}
index++
return result
} else {
return {
value: undefined,
done: true //done 为true value为undefined表示结束
}
}
}
}
}
}
// 要遍历jurisdiction
for (let item of obj) { //item是自命名 代表遍历中的每个元素
console.log(item);
}
13.生成器
生成器函数是 ES6 提供的一种异步编程解决方案。(后被promise代替 但还是有些需要使用,比如面试 哈哈哈哈)
function* gen() {
// yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码
yield '憨八龟';
yield "你在吗"
}
// 执行获取到的迭代器对象
let centre = gen()
// 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到yield 语句后的值
console.log(centre.next())
next 方法可以传递实参,作为 yield 语句的返回值
function* hen(num) {
console.log(num)
let one = yield "我的返回值是222";
console.log(one);
let two = yield "我的返回值是333";
console.log(two);
}
let centre = hen(111)
// **next 方法可以传递实参,作为 yield 语句的返回值**
centre.next() //注意第一个next 传参不会被V8引擎所识别 所以放在hen中传参
centre.next(222)
centre.next(333)
14.promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数, 用来封装异步操作并可以获取其成功或失败的结果。
这玩意太重要了,单独写了一篇。
15.Set结构
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯 一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进 行遍历。
//数组去重
let arr = [1, 2, 3, 2, 2, 4, 5]
let filter = [...new Set(arr)]
// 交集
let arr2 = [3, 3, 2, 4, 6]
let intersection = [...new Set(arr)].filter(item => new Set(arr2).has(item))
console.log(...intersection);
// 并集
let union = [...new Set([...arr, ...arr2])]
console.log(union);
Set的属性和方法
属性和方法 | 说明 |
---|---|
size | 返回集合元素的个数 |
add | 增加一个新元素 |
delect | 删除元素,返回布尔类型的值 |
has | 检测集合中是否包含某个元素,返回布尔类型的值 |
clear | 清空集合,返回 undefined |
16.Map结构
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键” 的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。
Map 的属 性和方法与Set相同:
属性和方法 | 说明 |
---|---|
size | 返回集合元素的个数 |
set | 增加一个新元素,返回当前 Map |
get | 返回键名对象的键值 |
has | 返回键名对象的键值检测 Map 中是否包含某个元素,返回 boolean 值 |
clear | 清空对象,返回 boolean 值 |
let m = new Map([
["name", "憨八龟"],
["age", 19]
]);
console.log(m);
17.class 类
ES6中引入类的概念,类抽取了对象的公共部分,泛指某一大类。
1.创建类
//语法:
class 类名{
}
//举例:
calss Super{
}
2.类constructor构造函数
作用:用于传递参数,返回实例对象。
constructor()方法是类的构造函数(默认方法),通过new命令生成实例时调用。
如果我们没有定义该方法,类的内部会自动创建。
class Super{
constructor(name,age){
this.name=name;
this.age=age
}
}
let demo = new Super("金骏眉",19)
console.log(demo)
3.类添加方法
**注意:**class类的方法之间不能加逗号分隔,且方法使用ES6增强写法 不要写function。
class Super {
constructor(name, age) {
this.name = name
this.age = age
}
// 对象方法
call() {
console.log("你好啊")
}
goodBy() {
console.log("再见了 " + this.name);
}
}
let demo = new Super("憨八龟", 18)
demo.goodBy() //输出:再见了 憨八龟
4.类的继承extends
class father {
constructor(type, vlaue) {
this.type = type;
this.vlaue = vlaue
}
show() {
console.log('我显示了');
return "显示"
}
hide() {
console.log("我隐藏了");
return "隐藏"
}
load() {
console.log("我加载了");
return "加载"
}
}
class son extends father { //继承了father的实例成员
hide() {
console.log("我是汉字");
}
text() {
console.log(this.type);
return this.type + 1
}
}
let demo = new son("文字", "值为0")
demo.show() //我显示了
demo.hide() //我是汉子 (根据原型链自己没有 才往上找)
demo.load() //我加载了
5. super关键字
用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通元素。
注意:
子类在构造函数中使用super,必须放在this之前使用。(必须先调用父类构造函数,在使用子类的构造方法)
class father {
constructor(type, value) {
this.type = type;
this.value = value
}
show() {
console.log('我显示了');
return "显示"
}
}
class son extends father { //继承了father的实例成员
constructor(type, value, name, age) {
super(type, value) //调用父元素的type,value属性
this.name = name
this.age = age
}
text() {
console.log(this.type);
console.log(this.value);
console.log(this.name);
console.log(this.age);
super.show() //super调用父类方法
}
}
let demo = new son("文字", "值为0", "憨八龟", 19)
demo.text()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2eC5v3V9-1617697250933)(images/17.class图A.png)]
6.class中getter和setter
getter和setter不是class所独有的,Vue中的计算属性底层 以及ES5中一些场合都有使用过。可以对对象的一些属性进行方法的绑定。
getter 当对某一属性执行获取时则去执行对应的函数。setter当对某一属性设置时触发。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ddrNNhzv-1617697250936)(images/17.class图B.png)]
代码:
/**
* @description: get 与 set
* @param {*}
* @return {*}
*/
let userList = [
{ id: 1, name: "小明",deposit: 200, },//存款
{ id: 2, name: "小红", deposit: 800, },
{ id: 1,name: "憨八龟", deposit: 1200, },
]
class Super {
constructor(list) {
this.list = list
}
//注意 这本质上还是一个属性 只是这属性调取get方法
//当获取该属性时调用get方法 return这个属性的值
get add() {
let sum = 0
for (let i = 0; i < this.list.length; i++) {
sum += this.list[i].deposit
}
return sum //return的 是add属性的值
}
// 注意 属性的set方法必须有参数传递
set add(user) {
console.log(user); //每次add值发生变化的时候打印值
}
}
let demo = new Super(userList)
//获取get 后的add属性值
console.log(demo.add);
//获取set后的getName属性值
demo.add = 333
demo.add = "憨八龟"
18. ES6数值类扩展
方法 | 说明 |
---|---|
Number.EPSILON | 表示最小经度 |
Number.isFinite | 检测一个数值是否为有限数 |
Number.isNaN | 检测一个数值是否为NaN |
Number.parseInt | 字符串转整数 |
Number.isInterger | 判断一个数是否为整数 |
Math.trunc | 将数字的小数部分抹除 |
Math.sign | 判断一个数是正数1 负数-1 零 0 |
19.ES6对象扩展
1.Object.is(NaN,NaN)
比较两个值是否严格相等,与『===』行为基本一致(+0 与 NaN)
2.Object.assign (合并对象1,合并对象2…)
合并规则: 合并对象1有一属性,而合并对象2没有则直接 添加。如果两个都有该属性后面的覆盖前面的。
3.Object.keys()
遍历出对象的所有键名。
let obj = {
name: "传奇",
age: 18,
hobby: ["篮球", "足球", "保龄球"]
}
//获取对象的所有键名
console.log(Object.keys(obj));
//打印结果:
["name", "age", "hobby"]
4.Object.values()
遍历出对象的所有值。
let obj = {
name: "传奇",
age: 18,
hobby: ["篮球", "足球", "保龄球"]
}
//获取对象的所有值
console.log(Object.values(obj))
5.Object.entries()
遍历出对象的所有键名和值。
let obj = {
name: "传奇",
age: 18,
hobby: ["篮球", "足球", "保龄球"]
}
console.log(Object.entries(obj));
6.Object.fromEntries()
Object.fromEntries 方法就是 entries 的逆操作,作用是将一个键值对数组转化为一个对象
let obj = {
name: "传奇",
age: 18,
hobby: ["篮球", "足球", "保龄球"]
}
let demo = Object.entries(obj)
console.log(Object.entries(demo));
console.log("---------------------------------------");
demo = Object.fromEntries(demo)
console.log(demo);
20.ES6数组扩展
1.includes()方法
Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值。
2.flat()方法
将多为数组转化为低维数组。
// flat 方法
// 这里包含三维数组
const arr = [1, [2, 3],[4, 5, [6, 7]]]
// flat 参数为深度 例如将三维数组降至一维数组
console.log(arr.flat(2)); //[1,2,3,4,5,6,7]
3.flatMap()方法
flatMap方法是数组方法map和flat的结合,因为map处理不了多维数组.
21.ES6字符串扩展
1.trimStart和trimEnd
ES5中使用.trim()方法清除字符串左右两端的空白字符
ES6新增trimStart和trimEnd方法分别清除字符串的左边、右边的空白字符。
21.ES6模块化
在Vue组件化章节有写
22.可选链操作符
// 可选链操作符有 ? .构成
//其中?判断是否有这个属性
//.则是回去这个属性
是否存在obj如果是 如果存在则继续执行
const pen = obj ? .NPC ? .content;