symbol
es6引入的一种原始数据类型,表示独一无二的值,一种类似于字符串的数据类型
特点:
- Symbol的值是唯一的,用来解决命名冲突的问题
- Symbol值不能与其他数据进行运算
- Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
创建symbol
let s = Symbol();
console.log(s,typeof s);//Symbol() "symbol"
let s2 = Symbol('xiaozhou');
let s3 = Symbol('xiaozhou');
console.log(s2 == s3);//false
let s4 = Symbol.for('xiaozhou');
let s5 = Symbol.for('xiaozhou');
console.log(s4 == s5);//true
不能与其他数据进行运算
let r = s +100;//报错
let r = s > 100;//报错
let r = s + '100';//报错
symbol的应用
向对象中添加up down方法
方法一
let game = {
};
//声明对象
let methods = {
up:Symbol(),
down:Symbol()
};
game[methods.up] = function(){
console.log("我可以上升");
}
game[methods.down] = function(){
console.log("我可以下降");
}
console.log(game);
//{Symbol(): ƒ, Symbol(): ƒ} 安全添加两个symbol方法到对象里面*/
方法二
let youxi = {
name : "狼人杀",
[Symbol('say')]:function(){
console.log("我可以发言");
},
[Symbol('zibao')]:function(){
console.log("我可以自爆");
},
}
console.log(youxi);
//{name: "狼人杀", Symbol(say): ƒ, Symbol(zibao): ƒ} 安全添加两个symbol方法到对象里面
内置symbol值
- hasInstance 当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法
- Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。
迭代器
迭代器( lterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署lterator接口,就可以完成遍历操作。
- ES6创造了一种新的遍历命令for…of循环,lterator接口主要供 for…of消费
- 原生具备iterator 接口的数据(可用for of遍历)
- Array
- Arguments
- set
- Map
- String
- TypedArray
- NodeList
声明一个数组
const xiyouji = ['唐僧','孙悟空','猪八戒','沙悟净','白龙马'];
//使用for...of比那里数组
for(let i of xiyouji){
console.log(i);
}//唐僧 孙悟空 猪八戒 沙悟净 白龙马 (键值)
for(let i in xiyouji){
console.log(i);
}//0 1 2 3 4 (键名)
工作原理
- a)创建一个指针对象,指向当前数据结构的起始位置
- b)第一次调用对象的next方法,指针自动指向数据结构的第一个成员
- c)接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
- d)每调用next方法返回一个包含value和 done属性的对象
注:需要自定义遍历数据的时候,要想到迭代器。
实现自定义遍历数组
const banji = {
name: '三班',
student:[
'zhangsan',
'lisi',
'wangwu',
'xiaoming'
],
[Symbol.iterator](){
let index = 0;
return{
next: () =>{
if(index<this.student.length){
const result = {value:this.student[index],done:false};
index++;
return result;
}else{
return{value:undefined,done:true};
}
}
}
}
}
//遍历数组
for(let i of banji){
console.log(i);//实现对象的遍历输出班级学生
}
生成器(其实就是有一个特殊的函数 用于异步编程)
生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同
function * gen(){
console.log('hello generator');
}
let iterator = gen();
console.log(iterator);//gen {<suspended>}此时这里并没有调gen函数
iterator.next();//hello generator 借助next方法来调用函数
function * gen(){
// console.log(111);
yield 'hello'; //yield 函数代码的分割符
// console.log(222);
yield 'world';
// console.log(333);
yield '!!!';
// console.log(444);
let iterator = gen();
iterator.next();//111
iterator.next();//222
iterator.next();//333
iterator.next();//444
}
for (let s of gen()) {
console.log(s);//hello world !!!
}
生成器函数参数
function * gen(){
let one = yield 'hello';
console.log(one);
yield 'world';
yield '!!!';
}
let iterator = gen();
console.log(iterator.next());//{value: "hello", done: false}
//next方法可以传入参数
iterator.next('aaa');//aaa
生成器函数实例1
异步编程 文件操作 网络操作(ajax,request) 数据库操作
1S后控制台输出 111 2S后输出 222 3S后输出 333
回调地狱
setTimeout(() =>{
console.log(111);
setTimeout(() =>{
console.log(222);
setTimeout(() =>{
console.log(333)
},3000)
},2000)
},1000)
function one(){
setTimeout(() =>{
console.log(111);
iterator.next();
},1000)
}
function two(){
setTimeout(() =>{
console.log(222);
iterator.next();
},2000)
}
function three(){
setTimeout(() =>{
console.log(333);
iterator.next();
},3000)
}
function * gen(){
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();//111 222 333
生成器函数实例2
模拟获取 用户数据 订单数据 商品数据
function getUsers(){
setTimeout(()=>{
let data = '用户数据';
//调用next方法,并且将数据传入
iterator.next(data);
},1000);
}
function getOrders(){
setTimeout(()=>{
let data = '订单数据';
iterator.next(data);
},1000);
}
function getGoods(){
setTimeout(()=>{
let data = '商品数据';
iterator.next(data);
},1000);
}
function * gen(){
let users = yield getUsers();
console.log(users);
let orders = yield getOrders();
console.log(orders);
let goods = yield getGoods();
console.log(goods);
}
//调用生成器函数
let iterator = gen();
iterator.next();
//用户数据 订单数据 商品数据
promise
Promise是ES6引入的异步编程的新解决方案。语法上 Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
- Promise构造函数: Promise (excutor){}
- Promise.prototype.then方法
- Promise.prototype.catch方法
实例化promise对象
const p = new Promise(function(resolve,reject){
setTimeout(function(){
// let data = '数据库中的数据';
//resolve 成功则调用
// resolve(data);
let err = '数据读取失败!';
//reject 失败则调用
reject(err);
},1000)
});
//调用promise 对象的then方法
p.then(function(value){//数据读取成功
console.log(value);
},function(reason){//数据读取失败
console.error(reason);
})
promise.property.then 方法
调用then方法 then方法的返回结果是 Promise对象,对象状态由回调函数的执行结果决定
1.如果回调函数中返回的结果是非promise类型的属性,状态为成功,返回值为对象的成功的值
const result = p.then(value =>{
console.log(value);
//1、非promise 类型的属性
return '123';
/* Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "123" */
//2、是promise对象
return new Promise((resolve,reject)=>{
resolve('ok');
})
/* Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "ok" */
//3、抛出错误
throw '出错啦!';
/* Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: "出错啦!" */
},reason =>{
console.error(reason);
});
链式调用
p.then(value =>{},reason=>{}).then(value=>{},reason=>{})
console.log(result);
promise catch方法(关于失败的回调)
p.catch((reason)=>{
console.error(reason);//03.html:319 数据读取失败!
})
set
ES6提供了新的数据结构 set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用「扩展运算符』和「 for…of…』进行遍历,集合的属性和方法:
- size 返回集合的元素个数
- add 增加一个新元素,返回当前集合
- delete删除元素,返回boolean值
- has 检测集合中是否包含某个元素,返回boolean值
声明一个set
let s = new Set();
let s2 = new Set([1,2,3,4,4]);//传入数组
console.log(s,typeof s);//Set(0) {} "object"
console.log(s2);//Set(4) {1, 2, 3, 4} 自动去重
元素个数
console.log(s2.size);//4
添加新的元素
s2.add(5);
console.log(s2);//Set(5) {1, 2, 3, 4, 5}
删除元素
s2.delete(2);
console.log(s2);//Set(4) {1, 3, 4, 5}
检测
console.log(s2.has(4));//true
清空
s2.clear();
console.log(s2);//Set(0) {}
使用for…of遍历set
for (let s of s2) {
console.log(s);// 1 2 3 4
}
set 实践
let arr = [1,2,4,5,6,3,1,5,2,3,7,8];
1、数组去重
// An highlighted block
var foo = 'bar';
/* let result = [...new Set(arr)];
console.log(result); *///[1, 2, 4, 5, 6, 3, 7, 8]
//2、交集
// An highlighted block
var foo = 'bar';
// let arr2 = [4,5,6,4,3,9];
// let result = [...new Set(arr)].filter(item=>{
// let s2 = new Set(arr2);
// if(s2.has(item)){
// return true;
// }else{
// return false;
// }
// })
//简化语句
let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
console.log(result);//[4, 5, 6, 3]
并集
let union = [...new Set([...arr,...arr2])];
console.log(union);//(9) [1, 2, 4, 5, 6, 3, 7, 8, 9]
差集
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
console.log(diff);//[1, 2, 7, 8]
map
ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用「扩展运算符』和「 for …of…』进行遍历。Map的属性和方法:
- size 返回Map的元素个数
- set 增加一个新元素,返回当前Map
- get 返回键名对象的键值
- has 检测 Map中是否包含某个元素,返回boolean值
- clear 清空集合,返回undefined
创建map
let m = new Map();
添加元素
m.set('name','xiaozhou');
console.log(m);//Map(1) {"name" => "xiaozhou"}
m.set('change',function(){
console.log("改变!");
});
let key = {
school:'abc'
};
m.set(key,[1,2,3]);
console.log(m);
//Map(3) {"name" => "xiaozhou", "change" => ƒ, {…} => Array(3)}
/*2: {Object => Array(3)}
key: {school: "abc"}
value: (3) [1, 2, 3]*/
size
console.log(m.size);//3
删除
m.delete('name');
console.log(m);//Map(2) {"change" => ƒ, {…} => Array(3)}
获取
console.log(m.get('change'));
/*ƒ (){
console.log("改变!");
}*/
清空
m.clear();
console.log(m);//Map(0) {}
for…of遍历
for (let s of m) {
console.log(s);
}
/* (2) ["change", ƒ]
(2) [{…}, Array(3)] */