【学习前端第四十四课】ECMAScript 6

ECMAScript 6

之前我们学习过ES5,它是JavaScript中的一部分,主要讲的都是变量,数据类型,控制流程,函数,面向对象等等

ES6 全称ECMAScript 6,也叫ECMAScript 2015,因为它是2015年定型发布的,它是新一代的js的语法标准,我们只涉及到ES不涉及DOM与BOM

ES6主要技术如下:

1、变量、常量

2、取值与赋值,解构

3、运算符的扩展,展开运算符,指数运算符

4、字符串的扩展

5、数组的扩展

6、函数的扩展

7、Set单值集合

8、Map键值对集合

9、对象的扩展与class关键字

10、生成器与迭代器与迭代器接口

11、反射Reflect

12、代理Proxy

13、Promise异步处理,async 及 await

14、ES6的模块话 ESModule

15、CommonJS模块化

let定义变量

之前在ES5里面,我们定义变量使用 var 这个关键字有几个特点说明一下

1、var 没有数据类型

2、var 是由一个建立阶段

3、var 是没有作用域的,它要通过函数才能形成作用域

//var没有数据类型
var a = 1;

//var没有作用域
{
    var b = "haha"
}
console.log(b);

//var有一个建立阶段,可以在定义之前调用
console.log(c);
var c = 123;

var在定义变量的过程中其实并不严谨

为了让变量声明的过程更加严谨,ES6就推出了 let 用于定义变量

1、let定义的变量也没有数据类型

2、let没有建立阶段,必须先定义后使用

let aa = "hello";
console.log(aa);    //没有问题的


console.log(bb);    //这里会报错,因为let没有建立阶段
let bb = "world";

3、let定义的变量是有作用域的,以花括号作为作用域

{
    let c = "haha";
    console.log(c);   //没有问题的 
}
console.log(c);    //会报错,告诉你c is not defined

4、let在同一作用域下不允许重复定义

let a = 123;
let a = 456;   //这里是会报错
{
    let a = "haha";   //这里没有问题
}
暂时性死区

let有它自身的特点,所以在使用的时候有一些现象需要注意,这种现象叫暂时性死区

let定义的变量是有作用域的,并且不能再定义之前调用

let a = "hello";
{
    console.log(a);  //这里是没有问题的,因为内部可以使用外部的变量
}

但是如果把代码改成如下的情况

let a = "hello";
{
    console.log(a);    //这里就会形成一个暂时性死区
    let a = "world";
}

const常量

  • 变量:可以变化的数据叫变量
  • 常量:不会变化的数据叫常量,如 Math.PI

const是定义常量的关键字,它具备上面的let的所有特点,同时又不能改变值

let a = "hello";
console.log(a);
a = "world";
console.log(a);

const b = "yoxi";
console.log(b);
b = "heihei";   //这里会报错

总结:

1、没有建立阶段

2、会形成块级作用域,以花括号为区域

3、只能初始化赋值,后期不能改变值

const的锁栈与锁堆原理

const常量,只锁栈,不锁堆

如果const声明的常量里面报存的是一个引用类型,那么根据只锁栈,不锁堆的原则,我们是可以改变数据中的属性值,但是无法整体覆盖掉之前的数据

const常量定义的时候一定要赋予初始化,不然没有任何意义

const a;   //毫无意义
let与const的闭包特性
<button type="button" class="btn">按钮0</button>
<button type="button" class="btn">按钮1</button>
<button type="button" class="btn">按钮2</button>
<button type="button" class="btn">按钮3</button>
<button type="button" class="btn">按钮4</button>
<script type="text/javascript">
    var btns = document.querySelectorAll(".btn");
    for(var i = 0; i < btns.length;i++){
        btns[i].addEventListener("click",function(){
            console.log(i);
        })
    }
</script>

根据我们的分析,我峨嵋你认为按钮点击的时候应该是第0个按钮打印0,最后一个按钮打印4,结果实际情况是每个按钮都打印5,这是为什么?

分析原理: 在进行循环的时候,i是0-4进行的,所以会把所有的按钮都遍历一遍,然后添加事件绑定,当i = 5结束循环,事件绑定结束。

直接去点击click事件的时候,我们 要打印是i,但是这个时候 i 已经是5了 ,因为var定义的变量没有区域性,打印的console.log(i) 其实还是for徐娜混定的 var i的变量

ES5闭包解决
var btns = document.querySelectorAll(".btn");
for(var i = 0; i < btns.length;i++){
    btns[i].addEventListener("click",(function(j){	
        var j = i
        return function(){
            console.log(j)
        }
    })(i))
}
ES6的let解决
var btns = document.querySelectorAll(".btn");
for(let i = 0; i < btns.length;i++){
    btns[i].addEventListener("click",function(){
        console.log(i);
    })
}

分析:因为let定义的变量是具有区域性的,所以上面的代码相当于在循环内,定义了5个let i;

{
	let i = 0;
}
{
	let i = 1;
}
//.......
//依次类推,每个花括号都是一个作用域 ,不影响外边

解构

ES6里面一大特色就是解构,它是一种特殊的取值赋值的方式

解构取值

1、数组的解构取值

let arr = ["张三","李四"];
// let a = arr[0];
// lat b = arr[1];

let [a,b] = arr;
console.log(a);
console.log(b);

对于复杂的数组也可以是现实深度解构

let arr = ["张三","李四",["王五","赵六"]];

let [a,b,[c,d]] = arr;
console.log(a);
console.log(b);
console.log(c);
console.log(d);

解构还可以变量置换

let a = 10;
let b = 20;
[a,b] = [b,a];
console.log(a,b);

2、对象的解构取值

var userInfo = {
    userName: "张三",
    age: 20
}

let {userName,age} = userInfo;
console.log(userName,age);

对象也可以进行深度的解构取值

var userInfo = {
    userName: "张三",
    age: 20,
    phone:{
        price:2999,
        brand:"xiaomi"
    }
}

let {
    userName,
    phone:{
        price
    }
} = userInfo
console.log(userName,price);
解构赋值

解构赋值其实就是解构取值的反向操作,这个过程只发生在对象里面,所以也叫对象的解构赋值

let userName = "张三";
let age = 18;
let userInfo = {
    userName: userName,
    age: age
}

在上面的代码当中,我们发现属性名和属性值是相同的,这个时候要注意,这种情况完全可以简化成解构赋值

let userName = "张三";
let age = 18;
let userInfo = {
    userName,
    age
}
console.log(userInfo);

展开运算符

它是ES6里面新出的运算符,所有实现了 Iterable这个接口的都可以使用展开运算符,目前系统ES里里面实现这个接口的数据类型如下

1、数组

2、NodeList

3、HTMLCollection

4、Set

5、Map

6、arguments

展开运算符在ES6里面使用 ... 来完成

let arr = ["a","b","c","d","e"];
console.log(arr);
console.log(...arr);

通过展开运算符得到数组中最大的数字

let arr1 = [1,5,8,2,4,9];
var max1 = Math.max(...arr1);
console.log(max1);

展开运算符实现数组的拷贝

var arrStr = ["张三","李四","王五"];
//创建一个arrStr2
//arrStr2与arrStr相同
//两个数组之间互不影响
//var arrStr2 = arrStr.concat();
//var arrStr2 = arrStr.slice();

var arrStr2 = [...arrStr];
console.log(arrStr2);

还可以将类数组转换成数组

var lis = document.querySelectorAll(".ul1>li");
//$(lis).toArray();
//$.makeArray(lis);
//var arr1 = Array.prototype.slice.call(lis);

var arr2 = [...lis];

使用展开运算符合并数组

var arr1 = ["a","b","c"];
var arr2 = [1,2,3];
var arr3 = ["张三","李四"];

var arr4 = arr1.concat(arr2).concat(arr3);
let arr5 = [...arr1,...arr2,...arr3];
console.log(arr5);

使用展开运算符实现对象的拷贝

let obj1 = {
    userName:"张三",
    age:18
}


// Object.assign(obj3,obj1);

let obj3 = {
    ...obj1
}
console.log(obj3);

使用展开运算符实现对象的合并

let obj1 = {
    userName:"张三",
    age:18
}
let obj2 = {
    hobby:"睡觉"
}


// Object.assign(obj3,obj1,obj2);

let obj3 = {
    ...obj1,
    ...obj2
}
console.log(obj3);

字符串扩展

模板字符串,模板字符串的一大特征就是自带格式,你格式是什么样子的,你输出的时候就长什么样

var str = `
    亲爱的XXX:
        你好!
        恭喜你!你已中了本公司的特等奖,价值9999元的礼包直接领回家!
        您只需要交纳1999元的保证金即可领取大奖,具体详情欢迎咨询我们的客户人员
    电话:123456678
    联系人:XXXX


                                                        XXX公司
                                                        XXXX年XX月XX日
`
console.log(str);

怎么书写就怎么生成,很方便

模板字符串另外一个特点就是可以快捷的实现字符串拼接

let nickName = "张三";
    let tel = "027-110"
    let connectPerson = "李四";
    let company = "皮皮虾公司"
    let str = `
        亲爱的${nickName}:
            你好!
            恭喜你!你已中了本公司的特等奖,价值9999元的礼包直接领回家!
            您只需要交纳1999元的保证金即可领取大奖,具体详情欢迎咨询我们的客户人员
        电话:${tel}
        联系人:${connectPerson}


                                                           ${company}公司
                                                           ${new Date().toLocaleString()}
    `
    console.log(str);

模板字符串里面 ${} 这里面可以写任何的js代码

模板字符串的注意事项
function abc(){
    console.log("hello");
}
abc``;

模板字符串的反引号可以当成方法的括号去执行

let userName = "张三";
let age = 18;
let sex = "男"

function abc(){
    console.log(arguments);
}
abc`xxxx${userName}yyyy${age}zzzzz${sex}`;

以上的写法会把字符串当前实参传入,同时 符号作为分隔符,将字符串的部分进行数组存放,并且 {} 符号作为分隔符,将字符串的部分进行数组存放,并且 符号作为分隔符,将字符串的部分进行数组存放,并且{}内部的js语句的执行结果分别作为单个实参传入

字符串扩展方法

1、includes() 判断当前字符串当中是否包含某个字符串,以前使用 indexOf或者是 lastIndexOf

2、repeat() 生成一个重复的字符串

3、trimStart() 去除开始的空格

4、trimEnd() 去除结束的空格

数组的扩展方法

ES6又多了很多方法

1、Array.of()方法

它是一个数组定义的方法,解决了之前 new Array() 所存在的问题

let arr = new Array(2);  //代表这个数组的长度是2
let arr2 = Array.of(2);   //代表给数组添加了一个2的元素
let arr3 = [2];           //上面的写法等价于这句

Array.of() 等价于 [],所以肯定也可以这么写

let arr2 = Array.of(2,3,5,7);

2、Array.from()

把类数组转换成数组

var lis = document.querySelectorAll(".ul1>li");
//$(lis).toArray();
//$.makeArray(lis);
//var arr1 = Array.prototype.slice.call(lis);

var arr2 = [...lis];
let arr3 = Array.from(lis);

3、Array.prototype.fill() 填充数组的方法

这个方法需要传参

参数一:需要填充的数据

参数二:需要从索引几开始填充

参数三:填充到索引几

let arr1 = new Array(100);
arr1.fill("abc");
console.log(arr1);

let arr2 = new Array(100);
arr2.fill("张三",0,20);
console.log(arr2);

let arr3 = new Array(100);
arr3.fill("李四",15,30);
console.log(arr3);

4、Array.prototype.flat(steps) 拍平一个多维数组

以前我们如果需要将多维数组拍平,我们要使用递归遍历,现在又这个方法就简单多了

let arr = [1,2,["z","y",["123",[true,false],"222"]]]
let arr2 = arr.flat(Infinity);
console.log(arr2);

参数 steps 代表要拍平多少层,如果想把整个多维数组转换成一维数组,可以直接传一个参数 Infinity 即可

5、Array.prototype.find()

let list = [
    {
        userName:"张三",
        age:18
    },
    {
        userName:"李四",
        age:18
    },
    {
        userName:"王五",
        age:18
    },
    {
        userName:"张三",
        age:20
    }
]

var obj = list.find(function(item,index,_arr){
    //返回匹配条件的对象
    return item.userName == "张三";
})
console.log(obj);

找到了就返回第一次找到的元素,如果找不到返回 undefined

6、Array.prototype.findIndex() 查找某一个元素的索引,这个方法的使用于上面的一样

var index = list.findIndex(function(item,index,_arr){
    return item.userName == "张三";
})
//返回的是匹配条件的对象的索引
for…of遍历

of的遍历于之前 的in遍历是相同的,只是 for…in遍历时一个有序遍历(有索引的时候依靠索引),而for…of称之为无序遍历(遍历的时候不需要索引)

for…of是基于属性值的遍历,但是并不是所有的对象都可以使用它来遍历,如果要使用for…of来遍历,则这个对象必须要实现 Iterable 接口

let arr = ["a","b","c","d"];
//基于属性名遍历,相当于是基于索引遍历
for(let i in arr){
	console.log(arr[i]);
}

//for...of是基于属性值遍历的,也就是不需要索引
for(let i of arr){
	console.log(arr[i]);
}

Set单值集合

Set是ES6里面新增的一个数据解构,它是一种单值集合,没有属性名(没有索引,没有key),并且是一个不重复的集合

Set创建
let s1 = new Set();   //创建了一个空的set单值集合
let s2 = new Set(["a","b","c","d"]);   
let s3 = new Set(["a","b","c","c","d"]);   //不能重复粗,所以得到的结果是a,b,c,d
Set方法

1、add() 向set集合里面添加新的元素

s3.add("haha");
s3.add("haha").add("hehe");

2、delete() 向set集合中删除某个元素,返回布尔值结果

let result = s3.delete("a");

3、has() 判断set集合当中有没有指定元素,返回布尔值

let result = s3.has("a")    //true

4、size 属性,表示set集合中的元素个数

5、clear() ,清空当前集合

6、values() ,它是一个生成器方法,返回当前Set集合中值的迭代器 Iterator

7、keys() 它也是一个生成器方法,返回当前set集合中键的迭代器,但是set没有键,所以返回依然是values的结果

set的遍历

set因为是单值的无序集合,所以没有索引,那么就不能使用 for…in 进行遍历,而for…of是基于属性值遍历,同时set又实现了 iterable 接口,所以它完全可以使用for…of进行遍历

let s2 = new Set(["a","b","c","d"]);
for(let i of s2){
	console.log(i);
}
set集合扩展,使用set对数组去重
let arr = ["a","b","c","d","d","c"];
//请将上面数组去重
let s4 = new Set(arr);
let arr1 = [...s4];
console.log(arr1);

Map键值对集合

map集合相对于上面的set集合的单值存在,map是键值对形式的一种储存,它结合set的储存特点(存取速度快),也解决了获取的缺点(获取速度慢)

Map集合当中的键是不允许重复的,但是值可以重复

let m1 = new Map(); 
//直接静态初始化
let m2 = new Map([
    ["a","张三"],
    ["b","李四"],
    [1,"王五"]
])
//键是不会重复的,值可以重复,键同名的时候,后面出现的值会覆盖掉前面出现的值
let m3 = new Map([
    ["a","张三"],
    ["b","李四"],
    ["c","哈哈"],
    ["d","呵呵"],
    ["b",123],
    [1,"王五"],
    [2,{
        userName: "yoxi"
    }],
    ["e",function(){
        console.log("hello");
    }]
])

1、键不能重复,值可以重复

2、键与值可以是任意数据类型

Map的方法

1、size 属性,用于表示有多少对元素

2、set(k,v),向Map集合内部添加一对元素

let m1 = new Map();

m1.set("a","张三");
m1.set("b","lisi").set(1,"王五")

3、get(key) 通过一个键向Map集合当中取一个值

var x = m1.get("a");
var y = m1.get(1);

4、delete(key) 通过一个键删除一个元素

m1.delete("b");

5、clear() 清空当前Map集合

6、values() ,它是一个生成器方法,返回当前Map集合中值的迭代器 Iterator

7、keys() 它也是一个生成器方法,返回当前Map集合中键的迭代器 Iterator

8、entries() 它是一个生成器方法,返回当前Map集合中的 key-value集合

Map的遍历

Map是实现了迭代器接口的,所以可以用for…of 来遍历,但是 Map 散列储存,所以没有索引的说法,所以不能用for…in

let m1 = new Map();

m1.set("a","张三");
m1.set("b","lisi").set(1,"王五")

for(let i of m1){
	console.log(i)
}

这个时候 i 代表是 key和value的组合,这个时候我们可以直接使用解构来进行遍历

for(let [k,v] of m1){
	console.log(k,v);
}
  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值