2.1 Symbol
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
大家可以这样记:
USONB
u: undefined
s : string symbol
o: object
n: null number
b: boolean
非常的简便。
Symbol 值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
基本语法:
<script>
let k = Symbol();
console.log(typeof k);
</script>
输出结果为symbol。
注意:Symbol函数前不能用new命令。因为Symbol的值不是对象,所以不能添加属性。
Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
<script>
let s1 = Symbol('foo');
let s2 = Symbol('bar');
console.log(s1); // Symbol(foo)
console.log(s2); // Symbol(bar)
console.log(s1.toString()); // "Symbol(foo)"
console.log(s2.toString()); // "Symbol(bar)"
</script>
上面代码中,s1和s2是两个 Symbol 值。如果不加参数,它们在控制台的输出都是Symbol(),不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。
作为属性名的 Symbol:
由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。
有很多种写法,我们一起来看看:
<script>
let mySymbol=Symbol();
//第一种
let a = {};
a[mySymbol]='hello';
//第二种
let b ={
[mySymbol]:'hello'
};
//第三种
let c = {};
Object.defineProperty(c,mySymbol,{value:'hello'})
console.log(a);
console.log(b);
console.log(c);
</script>
大家可以看出得到的结果是一致的。
2.2 迭代器
遍历器(iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署lterator接口,就可以完成遍历操作。
1)
2)原生具备 iterator 接口的数据(可用 for of 遍历)
Array Arguments Set Map String TypeArry NodeList
3)工作原理
a)创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
d)每调用 next 方法返回一个包含 value 和 done 属性的对象
注意:需要自定义遍历数据的时候,要想到迭代器。
<script>
//声明一个数组
const xiyou = ['唐僧', '孙悟空', '猪八戒', '沙僧'];
let iterator = xiyou[Symbol.iterator]();
//调用对象的next方法
console.log(iterator);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
</script>
为对象添加iterator接口:
<script>
//声明一个对象
const banji = {
name: "终极一班",
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
[Symbol.iterator]() {
//索引变量
let index = 0;
//
let _this = this;
return {
next: function () {
if (index < _this.stus.length) {
const result = { value: _this.stus[index], done: false };
//下标自增
index++;
//返回结果
return result;
} else {
return { value: undefined, done: true };
}
}
};
}
}
//遍历这个对象
for (let v of banji) {
console.log(v);
}
</script>
2.3 生成器
生成器函数(function *)是ES6提供的一种异步编程解决方案,语法和传统函数大不相同。生成器函数简单理解就是这个函数返回一个可枚举的对象(官方说法返回Generator
<script>
function * gen() {
yield '你好';
yield '你真好';
yield '你太好了';
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
</script>
注意:
- *的位置没有限制,靠近左边、右边、中间都可以。
- 生成器函数返回的结果是迭代器对象,调用迭代器对象的next方法可以得到yield语句中的值。
- yield相当于函数的暂停标记,也可以认为是函数的分隔符,每一次调用next方法,都会执行一次。
- next方法可以传递实参,作为yield的返回值。
2.4 promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
1)Promise 构造函数: Promise (excutor) {}
2)Promise.prototype.then 方法
3)Promise.prototype.catch 方法
promise基本语法:
<script>
//实例化promise对象
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// let data = '用户数据';
// resolve(data);
let err = '失败';
reject(err);
}, 1000)
});
//调用promise对象的then方法
p.then((value) => {
console.log(value);
}, (reason) => {
console.error(reason);
})
</script>
调用resolve生成的结果。
调用reject生成的结果。
promise-then 方法:
<script>
//创建promise对象
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('用户数据');
// reject('出错了');
}, 1000)
})
//调用then方法,then方法的返回结果是promise对象,对象状态由回调函数所执行的结果决定
//如果回调函数返回的结果是‘非promise’属性,promise状态为成功,返回的值为对象成功的值
p.then(value => {
console.log(value);
return 521;
}, reason => {
console.warn(reason);
})
</script>
promise-catch 方法:
<script>
const p =new Promise((resolve,reject)=>{
setTimeout(()=>{
reject('失败了');
})
},1000)
p.catch(function(reason){
console.warn(reason);
})
</script>
2.5 Set
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
- size 返回集合的元素个数
- add 增加一个新元素,返回当前集合。
- delete 删除元素,返回布尔值
- has 检测集合中师傅包含某个元素,结果返回布尔值。
- clear 清空集合,返回undefined。
<script>
//声明一个 set
let s = new Set();
let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);
//元素个数
console.log(s2.size);
//添加新的元素
s2.add('喜事儿');
//删除元素
s2.delete('坏事儿');
//检测
console.log(s2.has('糟心事'));
//清空
s2.clear();
console.log(s2);
for(let v of s2){
console.log(v);
}
</script>
set 集合实践
//数组去重
let arr = [1,2,3,4,5,4,3,2,1];
//数组去重
let result = [...new Set(arr)]
console.log(result);
//交集
let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
//交集
let arr1 = [4, 5, 6, 2, 3];
let result = [...new Set(arr)].filter(function (item) {
let s = new Set(arr1);
if (s.has(item)) {
return true;
} else {
return false;
}
});
console.log(result);
//并集
let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let arr1 = [4, 5, 6, 2, 3];
//先合并数组再进行去重
let newArr = [...new Set([...arr,...arr1])];
console.log(newArr);
//差集
let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let arr1 = [4, 5, 6, 2, 3];
let cha = [...new Set(arr)].filter(item => !(new Set(arr1).has(item)));
console.log(cha);
2.6 Map
因为JavaScript中的对象,本质上是键值对的集合,但是传统上只能用字符串当作键,这意味着带来了很大的限制。
为了解决这个问题,ES6向我们提供了Map这种数据结构,他类似于对象,但是键的范围不限于字符串,大多数数据类型的值都可以当作键,所以如果需要键值对的数据结构Map比Object更加合适。Map 也实现了iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map 的属性和方法:
- size 返回Map的元素个数。
- set 增加一个新元素,返回给Map.
- get 返回键名对象的键值。
- has 检测Map中是否包含某个元素,返回布尔值。
- clear 清空集合,返回undefined。
声明Map:
let m = new Map()
添加元素:
let m = new Map()
m.set('name', 'XATU');
m.set('change', function () {
console.log('兵工七子');
})
console.log(m);
删除元素:
m.set('name', 'XATU');
m.set('change', function () {
console.log('兵工七子');
})
m.delete('change');
console.log(m);
获取get:
//声明Map
let m = new Map()
m.set('name', 'XATU');
m.set('change', function () {
console.log('兵工七子');
})
// m.delete('change');
console.log(m.get('name'));
清空 clear:
m.clear();
遍历:
let m = new Map()
m.set('name', 'XATU');
m.set('change', function () {
console.log('兵工七子');
})
for (let k of m) {
console.log(k);
}
console.log(m);
2.7 class
通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
class Shouji{
constructor(brand,price){
this.brand=brand;
this.price=price;
}
call(){
console.log('我可以打电话');
}
}
let mi = new Shouji('小米','1999')
console.log(mi);