本文为阅读和学习《ECMAScript 6 入门》的总结笔记,仅摘取重要的点记录一下。
涉及到的点:
##let与const##变量的解构赋值##数据结构set##数据结构map##iterator和for循环##class的使用与继承##Symbol数据类型##内置对象的扩展##函数的扩展##异步操作之promise##
-----------------------------------分-----------------------割-------------------------线---------------------------------------------------
一.let与const
1.仅在其所在的代码块中有效。
2.不存在变量提升。
3.暂时性死区。如果区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭的作用域,声明之前使用就报错。
4.不允许重复声明。
5.const声明了就必须初始化,且不能改变值。
ES5中有两种声明的方法:var和function。ES6又添加了let,const,import,class。所以es6一共有6种声明方法。
var和function声明的全局变量是全局对象的属性。let,class,const声明的全局变量不是全局对象的属性。
二.变量的解构赋值
本质上就是一种匹配模式,只要等号两边的模式相同,那么左边的变量就可以被赋予对应的值。
结构赋值主要分为:
1 数组的解构赋值:只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值。
2 对象的结构赋值
3 基本类型的解构赋值
三.数据结构Set
集合是由一组无序且唯一(即不能重复)的项组成的。key 和 value 相同,没有重复的 value。
它类似于数组,但是成员的值都是唯一的,没有重复的值。
1.创建Set
const s = new Set([1, 2, 3]);
2.Set的属性
console.log(s.size); // 3
3.Set的方法
set.add(value) 添加一个数据,返回Set结构本身。
set.delete(value) 删除指定数据,返回一个布尔值,表示删除是否成功。
set.has(value) 判断该值是否为Set的成员,反回一个布尔值。
set.clear() 清除所有数据,没有返回值。
keys() 返回键名的遍历器。
values() 返回键值的遍历器。
entries() 返回键值对的遍历器。
forEach() 使用回调函数遍历每个成员。
s.add('a').add('b').add('c'); console.log(s.delete('a')); console.log(s.has('a')); // false console.log(s.has(1)); // true console.log(s.keys()); console.log(s.values()); console.log(s.entries()); s.forEach(function (value, key, set){ console.log(value + ' miaov'); });
四.数据结构Map
即字典。用来存储不重复key的Hash结构。不同于集合(Set)的是,字典使用的是[键,值]的形式来储存数据的。
JavaScript 的对象(Object:{})只能用字符串当作键。这给它的使用带来了很大的限制。为了解决这个问题,ES6提供了Map数据结构。它类似于对象,也是键值对的
集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应,
是一种更完善的Hash结构实现。
1.创建一个Map
const map = new Map([ ['a', 1], ['b', 2] ]);
2.Map类的属性
console.log(map.size);
3.Map类的方法
set(key, value) 设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。
get(key) get方法读取key对应的键值,如果找不到 key,返回undefined。
delete(key) 删除某个键,返回true。如果删除失败,返回false。
has(key) 方法返回一个布尔值,表示某个键是否在当前Map对象之中。
clear() 清除所有数据,没有返回值。
keys() 返回键名的遍历器。
values() 返回键值的遍历器。
entries() 返回键值对的遍历器。
forEach() 使用回调函数遍历每个成员。
注意:
a.Map中认为NaN是用一个键。
map.set(NaN, 10).set(NaN, 100); console.log(map); //NaN=>10
b.Map对象的值是跟内存地址绑定的,所以会有两个空对象分别指向x和y:
map.set({}, 'x').set({}, 'y'); console.log(map); //object{}=>'x',object{}=>'y' console.log({} === {}); //false
c.Map里面key是按添加顺序排列的。
五.Iterator和for...of循环
新增了Set和Map两种数据结构,再加上JS之前原有的数组和对象,这样就有了四种数据集合。
平时还可以组合使用它们,定义自己的数据结构,比如数组的成员是Map,Map的成员是对象等。这样就需要一种统一的接口机制,来处理所有不同的数据结构。
Iterator就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作,而且这种遍历操
作是依次处理该数据结构的所有成员。
Iterator遍历器的作用:
- 为各种数据结构,提供一个统一的、简便的访问接口。
- 使得数据结构的成员能够按某种次序排列。
- ES6新增了遍历命令for...of循环,Iterator接口主要供for...of消费。
1.手写一个Iterator接口
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());
2.Iterator的遍历过程
- 创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
- 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
- 第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
- 不断调用指针对象的next方法,直到它指向数据结构的结束位置。
每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
3.凡是具有 Symbol.iterator 属性的数据结构都具有 Iterator 接口。
4.具备iterator接口的数据结构都可以进行如下操作。
- 解构赋值
- 扩展运算符:将一个数据结构进行展开。
利用这个,可以做数组去重:
const arr=[1,4,5,7,1,[],a,4,{},1]; console.log([...new Set(arr)]);
for...of循环
1.凡是具备iterator接口的数据接口都可以用for...of循环。
2.for...of内部调用的是symbol.iterator方法。
const ofArr = [1, 2, 3, 4]; for(let i of ofArr){ console.log(i); } const m = new Map(); m.set('a', 1).set('b', 2).set('c', 3); for(let [key, value] of m){ console.log(key, value); }
六.class
在ES6中新增加了类的概念,可以使用 class 关键字声明一个类,之后以这个类来实例化对象。
可以看做语法糖。
class PeriHe { constructor(a, b){ this.a = a; this.b = b; return this; } print(){ console.log(this.a + ' ' + this.b); } }; const PeriHe = new PeriHe('hello', 'world').print();
1. PeriHe中的constructor方法是构造方法,this关键字则代表实例对象。也就是说,ES5的构造函数PeriHe,对应ES6的PeriHe这个类的构造方法。
2. PeriHe这个类除了构造方法,还定义了一个print方法。定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。
3. 构造函数的prototype属性,在ES6的“类”上面继续存在。而且类的所有方法都定义在类的prototype属性上面。
4. 定义在类中的方法都是不可以枚举的。
5. constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
6. 生成类的实例对象的写法,与ES5完全一样,也是使用new命令。如果忘记加上new,像函数那样调用Class,将会报错。
class 的继承等相关知识
extends关键字实现继承。
static关键字为类指定静态方法。
super关键字调用父类原型上的方法或静态方法。
七.Symbol
表示独一无二的值。它是 JS 中的第七种数据类型。
基本的数据类型: Null Undefined Number Boolean String Symbol
引用数据类型:Object
let s1 = Symbol(); console.log(typeof s1); // 'symbol'
Symbol 函数前不能使用 new 否则会报错,原因在于 Symbol 是一个原始类型的值,不是对象。
Symbol 函数接收一个字符串作为参数,表示对Symbol的描述,主要是为了在控制台显示,或者转为字符串的时候,比较容易区分,没有其他意义。
1.Symbol 数据类型的转换
a.不能与其他类型的值进行运算,拼接也不行。
b.可以显示的转换成字符串。也可以转换成布尔值,但不能转换成数值。
console.log(String(Symbol('PeriHe'))); // Symbol(PeriHe) console.log(Symbol('leo').toString()); // Symbol(leo) console.log(!!Symbol()); // true console.log(Number(Symbol())); console.log(Symbol('momo') + 'pangzi'); console.log(Symbol('momo') * 100); 不能做任何运算。
2.作为对象的属性名
能防止某一个键被不小心改写或覆盖。
不能使用点运算符。
let yyy = Symbol('yyy'); const obj = {}; obj[yyy] = 'hello'; console.log(obj); console.log(obj[yyy]); let ss = Symbol('ss'); const data = { [ss]: 'PeriHe' }; console.log(data); console.log(data[ss]);
3.不能被for...in循环遍,虽然不能被遍历,但是也不是私有的属性,可以通过Object.getOwnPropertySymbols方法获得一个对象的所有的Symbol属性。
console.log(Object.getOwnPropertySymbols(data)); // [Symbol()] console.log(data[Object.getOwnPropertySymbols(data)[0]]);
八.对象的扩展
属性名与属性值相同可以简写。
Object.is():用来比较俩值是否严格相等。它与===运算符行为基本一致,不同之处只有两个:+0不等于-0;NaN等于NaN。
Object.assign():用于对象的合并。
九.函数的扩展
1 为函数参数指定默认值
2 函数的 rest 参数:rest 参数形式为(“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
a:rest参数中的变量代表一个数组,所以数组特有的方法都可以用于这个变量。
b:rest参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。
c;函数的length属性不包括rest参数。
3 箭头函数
- 箭头函数体内没有自己的this对象,所以在使用的时候,其内部的this就是定义时所在环境的对象,而不是使用时所在环境的对象。
- 不能给箭头函数使用 call apply bind 去改变其内部的this指向。
- 不可以当作构造函数,不可以使用new命令,否则会抛出一个错误。
十.异步操作之promise
是ES6中新增的异步编程解决方案,体现在代码中它是一个对象,可以通过 Promise 构造函数来实例化。
promise对象代表一个异步操作,有三种状态:Pending (进行中),Resolved (已完成也称Fulfilled),Rejected (已失败)。
两个原型方法:
- Promise.prototype.then():处理异步操作成功时要执行的回调函数。
- Promise.prototype.catch():处理异步操作失败时要执行的回调函数。
两个常用的静态方法:
- Promise.all() :可以将多个Promise实例包装成一个新的Promise实例。当所有Promise实例的状态都变成resolved,Promise.all的状态才会变成resolved。只要其中有一个被rejected,Promise.all的状态就变成rejected。
- Promise.resolve():将对象转为Promise对象。