ECMAScript6常用语法

let和const

let命令:用来声明变量,和var非常类似

  1. 所声明的变量只在所在的代码块内有效。
1
2
3
4
5
6
7
{
let a = 1;
var b = 2;
console.log(a) //1
}
console.log(a); //err not defined
console.log(b); //2
  1. 使用Let声明的变量在域解析的时候不会被提升。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
console.log(a); //err not defined
let a = 2;
console.log(b); //undefined
var b = 1;
typeof c; //err not defined
let c = 3;
let f = 10;
function fn() {
f = 7; //暂时性死去
let f = 2;
}
fn(); ////err not defined
  1. let不允许在同一个作用域下声明已经存在的变量。
1
2
3
4
5
var a = 1;
let a; //err
let a = 1;
let a = 2; //err

for循环的梗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var aLi = document.getElementsByTagName('li');
for(var i = 0; i < aLi.length; i++){
aLi[i].onclick = function() {
console.log(i);
}
}
// 得到是只会是aLi.length
for (var i = 0; i < aLi.length; i++) {
aLi[i].index = i
aLi[i].onclick = function () {
console.log(this.index);
}
}
// 添加自定义属性可以拿到每次循环的i
for (var i = 0; i < aLi.length; i++) {
(function (i) {
aLi[i].onclick = function () {
console.log(i);
}
})(i);
}
// 用闭包方式拿到每次循环的i
for(let i = 0; i < aLi.length; i++){
aLi[i].onclick = function() {
console.log(i);
}
}
// let直接搞定 拿到每次循环的i

在循环语句之内是父作用域,在循环体之中是一个子作用域

1
2
3
4
5
for (let i = 0; i < 3; i++) {
let i = 10;
console.log(i); //10 循环体的i不受循环语句内i的影响
}
console.log(i); //err not defined 循环体中的i外部访问不到

const命令:用来声明一个常量,常量就是不可以变化的量
const同样有let的三条特点,此外还要注意:
1 声明的时候必须赋值;
2 声明的常量储存简单的数据类型时候不可改变其值,如果储存的是对象,那么引用不可以被改变,至于对象里面的数据如何变化是没有关系的

1
2
3
const obj = { a : 10 };
obj.a = 20;
console.log(obj);//{ a : 20 }

变量的解构赋值

基本概念:本质上就是一种匹配模式,只要等号两边的模式相同,那么左边的变量就可以被赋予对应的值。
解构赋值主要分为:
1 数组的解构赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//let a = 1;
//let b = 2;
//let c = 3;
let [a, b, c] = [1, 2, 3];
console.log(a, b , c); //1 2 3
let [a, [ [ b ], c] ] = [1, [ [ 2 ], 3] ]
console.log(a, b , c); //1 2 3
let [, , c] = [1, 2, 3];
console.log(c); // 3
let [x] = [];
console.log(x); //undefined
let [y = 1] = [];
console.log(y); //1

2 对象的解构赋值

1
2
3
4
5
6
let {a,b} = {b: 'bbb', a: 'aaa'};
console.log(a,b); ///aaa bbb
let {a : b} = {a : 1};
console.log(b) //1
console.log(a) //err not defined

3 基本类型的解构赋值

1
2
3
4
5
6
7
let [a, b, c, d] = '1234';
console.log(a, b, c,d) // 1 2 3 4
let {length : len} = "adele";
console.log(len); //5
null和undefined不能被解构赋值

数据解构 Set

集合的基本概念:集合是由一组无序且唯一(即不重复)的项组成的,这个数据结构使用了与有限集合相同的数学概念,应用在计算机的数据结构中。
特点: key 和 value 相同 没有重复的value
ES6提供了数据结构Set,类似于数组,但是成员的值是唯一的,没有重复的值。
1 如何创建 Set

1
2
const s = new Set([1,2,3]);
console.log(s);

2 Set 类属性

1
console.log(s.size); // 3

3 Set类的方法
set.add(value) 添加一个数据,返回set结构本身

1
2
s.add('a').add('b').add('c');
console.log(s);

set.delete(value) 删除指定数据,返回一个布尔值,表示删除是否成功

1
2
console.log(s.delete('a'));
console.log(s);

set.has(value) 判断该值是否为set的成员,返回一个布尔值

1
2
console.log(s.has('a')); // false
console.log(s.has('1')); //true

set.clear() 清楚所有数据,没有返回值

1
2
s.clear();
console.log(s);

keys() 返回键名的遍历器

//键和值相同```
1
2
values() 返回键值的遍历器
```console.log(s.values()); //键和值相同

entries() 返回键值对的遍历器

//键和值相同```
1
forEach() 使用回调函数遍历每个成员

s.forEach(function (value, key, set){
console.log(value + “adele”);
})
console.log(s); //没有变化

1
2
3
4
5
6
7
8
9
10
**利用set为数组去重**
数据结构 Map
---
字典:是用来存储不重复key的hash结构。不同于集合(set)的是,字典使用的是[键, 值]的形式来储存数据的
JS的对象(object : {})只能用字符串当键,这给其使用带来很大限制
ES6的Map数据结构类似于对象,也是键值对的集合,但“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键。也就是说Object结构提供了“字符串-值”的对应,Map结构提供了 “值-值”的对应,是一种完美的Hash结构实现,如果你需要 “键值对”的数据结构,Map比Object更适合
1 如何创建一个 Map

const map = new Map([
[‘a’, 1],
[‘b’, 2]
]);
console.log(map);

1
2
2 Map 类的属性

console.log(map.size);

1
2
3
4
5
3 Map 类的方法
set(key, value) 设置键名key对应值为value,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则重新生成该值
```
map.set("adele", "fe").set("adai", "rd")

get(key) get方法读取key对应的键值,如果找不到key,返回undefined

delete(key) 删除某个键值,返回true,如果删除失败,返回false

has(key) 方法返回一个布尔值,表示某个键是否在当前Map对象之中

clear() 清楚所有数据,没有返回值

keys() 返回键名的遍历器

values() 返回键值的遍历器

entries() 返回键值对的遍历器

forEach() 使用回调函数遍历每个成员

map.forEach( function( key, value, map){
console.log(key + ‘:’ + value);
})

map使用的一些注意事项
map数据结构中NaN是同一个键
map里key的排列顺序按照添加的顺序排列

iterator和for-of循环

Iterator是一个接口,为各种不同的数据结构(数组、对象、Set、Map)提供统一的访问机制。任何数据结构只要部署Iterator接口就可以完成遍历操作,而且这种遍历操作时依次处理该数据结构的所有成员

Iterator遍历器的作用
为各种数据结构提供一个统一的、简便的访问接口
使得数据结构的成员能够按照某种次序排列
ES6新增了遍历命令for…of循环,Iterator接口主要供其消费。

1、手写Iterator接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const arr = [1, 2, 3];
function iterator(arr){
let index = 0;
return {
next: function () {
return index < arr.length ?
{value: arr[index++], done: false} :
{value: undefined, done: true};
}
}
}
const it = iterator(arr);
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

Iterator的遍历过程

  1. 创建一个指针对象,指向当前数据结构的起始位置,也就是说遍历器对象本质上就是一个指针对象
  2. 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员
  3. 第二次调用指针对象的next方法,指针指向数据结构的第二个成员
  4. 不断调用指针对象的next 方法,直到它指向数据结构的结束位置。

每一次调用next方法都会返回数据结构当前的成员信息。具体来说就是返回一个包含value 和done两个属性的对象。其中 value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。

  1. 凡是具有 symbol.iterator 属性的数据结构都具有 Iterator 接口
    arr、set、map(object没有symbol.iterator )
    具备iterator接口的数据结构都可以进行如下操作
    结构复制
    扩展运算符 (… 作用为将数据结构展开)

利用Set为数组去重

1
2
let arr = [{}, 1, 'a', 1, 'a', 'b', []];
console.log([...new Set(arr)]);

for…of循环

1
2
3
4
5
6
7
8
9
10
11
12
13
const ofArr = [1, 2, 3, 4];
for(let i of ofArr) {
console.log(i);//i为数据结构中的每一项
}
const m = new Map();
m.set('a', 1).set('b', 2).set('c', 3)
for(let data of m){
console.log(data);
}
for(let [key, value] of m){
console.log(key, value);
}

class的基本使用

ES6中新增加了类的概念,可以使用class 关键字声明一个类,之后以这个类来实例化对象

1
2
3
4
5
6
7
8
9
10
11
12
class Adele {
constructor(a, b){
this.a = a;
this.b = b;
return this;
}
print(){
console.log(this.a + ' ' + this.b);
}
}
const adele = new Adele('hello', 'word').print();

Adele中的constructor方法是构造方法,this关键字则代表实例对象

Adele这个类除了构造方法还定义了一个print方法。注意,定义“类”的方法时,前面不需要加上function这个关键字,直接把函数定义放进去就可以了,另外方法之间不需要逗号分隔,加了会报错。

构造函数的prototype属性在ES6的“类”上继续存在,而且类的所有方法都定义在类的prototype属性上面

定义在类中的方法都是不可以枚举的

constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显示定义,一个空的constructor方法会被默认添加

生成类的实例对象的写法与ES5完全一样,也是使用new命令,如果忘记加上new,像函数那样调用class将会报错

class的继承

子类继承父类使用estends 关键字
为父类指定静态方法使用 static 方法名字
super

在构造函数中可以当一个函数来使用,相当于调用父类的构造函数
在原型方法中可以当一个对象来使用,相当于父亲的原型对象,并且会自动绑定this到子类上

Symbol数据类型

Symbol表示独一无二的值,它是JS中的第七种数据类型。
基本数据类型:Null Undefined Number Boolean String Symbol
引用类型:Object

Symbol函数不能使用new否则会报错,原因在于Symbol是一个原始类型的值,不是对象

Symbol函数接受一个字符串作为参数,表示对Symbol的描述,主要是为了在控制台显示,或者转为字符串的时候比较容易区分。

Symbol数据类型转换:字符产、布尔值

内置对象的扩展

字符串扩展
新增模板字符串

1
2
3
4
5
6
7
8
9
10
11
let flag = true;
let html = `
<ul>
<li>
<span>${'首页'}</span>
<span class = "${flag ? 'show' : 'hide'}"></span>
</li>
</ul>
`;
console.log(html);

repeat():对字符串做一些重复的操作

1
2
3
let str1 = 'a';
let str2 = str1.repeat(3);
console.log(str2); //aaa

includes() 类似于indexOf() ,看是否包含某个字符串
startsWith() / endsWith() 看开头 / 结尾是否包含某个字符串

数组扩展
Array.from() 将类数组转化为数组

Array.of() 创建一个数组 类似于 []

find() 对数组进行筛选,没找到返回undefined
findIndex() 返回符合条件元素的下标,没找到返回-1

fill() 对数组进行填充

对象的扩展
对象的简洁表示法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let a = 1;
const obj = {
a : a
};
//键值相同,可以像下面的方式简写
const obj = {a};
const obj = {
fn1: function(){
console.log(1);
},
fn2(){
console.log(2); //简写可以不写function
}
}
obj.fn1();
obj.fn2();

Object.is() 判断两个对象是否一样,长的一样就成

Object.assign() 将多个对象进行合并

函数的扩展
1 为函数参数指定默认值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function fn(a, b){
a = a || 10;
b = b || 20;
console.log(a + b);
}
fn(); //30
fn(0, 10); //20 0为false取了后面的默认值
//ES6可以直接在参数里面赋值
function fn1(a = 10, b = 20) {
console.log(a + b);
}
fn1(); //30;
fn1(0, 10); //10

2 函数的 rest 参数
rest 参数形式为(”…变量名”),用于获取函数多余的参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中

1
2
3
4
5
6
7
8
9
function sum(a, ...arr) { //rest后面不能传参数
var res = a;
for (var i = 0; i < arr.length; i++) {
res += arr[i];
}
console.log(res);
}
sum(10,1, 2, 3, 4, 5);

3 箭头函数
使用“箭头”(=>)定义函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const fn = a => a;
const fn2 = function (a) {
return a;
}
console.log(fn(1)); //1
console.log(fn2(2)); //2
const fn3 = (a, b) => a + b;
console.log(fn3(1, 2));//3
//多行代码需要用中括号包裹起来
const fn4 = (a, b) => {
a = a * 2;
b = b * 2;
return a + b;
}
console.log(fn4(1, 2)); // 6
//返回值为对象需要用小括号包裹
const fn5 = (a, b) => ({a, b});
console.log(fn5(1,2));

箭头函数体内没有自己的this对象,所以使用时其内部的this就是定义是所在环境的变量,而不是使用时所在环境的对象。

不能给箭头函数使用call apply bind 去改变其内部的this指向

箭头函数体内没有arguments对象,如果要要用可以用rest参数代替

不可以当做构造函数,不可以使用new命令,否则会抛出一个错误

异步操作之Promise

Promise 是ES6中新增的异步编程解决方案,体现在代码中它是一个对象,可以通过 Promise 构造函数来实例化
new Promise(cb) ===> 实例的基本作用 Pending(正在进行) Resolved(已经完成) Rejected(已经失败)

Pending(正在进行) ===> Resolved(已经完成)
Pending(正在进行) ===> Rejected(已经失败)
两个原型方法
Promise.prototype.then() //处理成功后
Promise.prototype.catch() //捕获失败后的异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const imgs = [
'http://pic2116.ytqmx.com:82/2017/0531/35/9.jpg!960.jpg']
const p = new Promise(function(resolve, reject){
const img = new Image();
img.src = imgs[0];
img.onload = function (){
resolve(this);
};
img.onerror = function () {
reject(new Error('图片加载失败'));
};
});
p.then(function (img) {
console.log('图片加载完成');
document.body.appendChild(img);
}).catch(function (err) {
console.log(err);
})

两个常用的静态方法
Promise.all()
可以将多个Promise实例包装成一个新的Promise实例
当所有Promise实例的状态都变成resolved,Promise.all的状态才会变成resolved,此时 返回值组成一个数组,传递给then中的resolve函数。
只要其中有一个Rejected,Promise.all的状态就变成Rejected,此时第一个被reject的实例的返回值会传递给p的回调函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const imgs = [
'http://pic2116.ytqmx.com:82/2017/0531/35/9.jpg!960.jpg',
'http://pic2116.ytqmx.com:82/2017/0531/35/10.jpg!960.jpg'
]
function loadImg(url){
const p = new Promise(function(resolve, reject){
const img = new Image();
img.src = url;
img.onload = function (){
resolve(this);
};
img.onerror = function () {
reject(new Error('图片加载失败'));
};
});
return p;
}
const allDone = Promise.all([loadImg(imgs[0]), loadImg(imgs[1])]);
allDone.then(function (datas){
datas.forEach(function (item, i) {
document.body.appendChild(item);
});
}).catch(function (arr) {
console.log(arr);
})

Promise.resolve()
将一个对象转换为Promise对象
1 参数是Promise实例,将不做任何修改,原封不动地返回这个实例
2 j将对象转为Promise对象,然后立即执行thenable对象的then方法

1
2
3
4
Promise.resolve(
then(resolve, reject){
}
)

3 参数是一个基本数据类型或者不传参数,那么返回一个状态为 resolved的Promise 对象