关于ES6新特性的总结 2

简介: 关于ES6新特性的总结

10.迭代器

迭代器(iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署iterator接口,就可以完成遍历操作


ES6创造了一种新的遍历命令for...of循环,iterator接口主要供for...of消费

注:for...of遍历的是键值,for...in遍历的是键名

for...of不能对属性值进行修改,forEach()可以


原生具备iterator接口的数据(可用for...of遍历)


Array

Arguments

Set

Map

String

TypedArray

NodeList

工作原理:


  1. 创建一个指针对象,指向当前数据结构的起始位置
  2. 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
  3. 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
  4. 每调用next方法返回一个包含value和done属性的对象,done属性表示遍历是否结束
const food = ['鱼香肉丝','糖醋里脊','酸菜鱼']
for(let item of food){
    console.log(item)
}
let iterator = food[Symbol.iterator]()
console.log(iterator.next()) // {value: "鱼香肉丝", done: false}
console.log(iterator.next()) // {value: "糖醋里脊", done: false}
console.log(iterator.next()) // {value: "酸菜鱼", done: false}
console.log(iterator.next()) // {value: undefined, done: true} true 表示遍历已经结束

注:需要自定义遍历数据的时候,要想到迭代器


迭代器应用-自定义遍历数据(即自己手动实现一个迭代器)

// 声明一个对象
const school = {
    name: '三中',
    students: [
        'LiMing',
        'HanMeimei',
        'WangFang',
    ],
    [Symbol.iterator](){
        // 声明一个索引变量
        let index = 0
        return {
            next: ()=>{
                if(index < this.students.length){
                // if(index < 3){
                    const result = {value: this.students[index], done: false}
                    // 下标自增
                    index++
                    // 返回结果
                    return result
                }else{
                    return {value: undefined, done: true}
                }
            }
        }
    }
}
// 遍历这个对象
for(let item of school){
    console.log(item)
}

11.生成器

生成器本身是一个特殊的函数,生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数不同


执行生成器函数,返回的是一个迭代器对象,通过iterator.next()调用执行函数内语句

function * gen(){
    console.log('hello generator')
}
let iterator = gen() // 返回的是一个迭代器对象
// console.log(iterator)
// 通过.next()调用执行函数内语句
iterator.next() // hello generator

yield是函数代码的分隔符,结合调用iterator.next()方法,实现函数gen1的语句的分段执行

function * gen1(){
    console.log('--- 1 ---')
    yield '耳朵' // 函数代码的分隔符
    console.log('--- 2 ---')
    yield '尾巴'
    console.log('--- 3 ---')
}
let iterator1 = gen1()
iterator1.next() // --- 1 ---
iterator1.next() // --- 2 ---
iterator1.next() // --- 3 ---
// 通过调用.next()方法,实现函数gen1的语句的分段执行

使用for...of遍历函数执行后返回的迭代器对象,每一次遍历的item为yield后的表达式或者自变量的值

function * gen1(){
    yield '耳朵' // 函数代码的分隔符
    yield '尾巴'
}
// 遍历,每一次遍历的item为yield后的表达式或者自变量的值
for(let item of gen1()){
    console.log(item)
}
// 执行结果:
// 耳朵
// 尾巴
// 注:next调用和for...of调用同时存在,只会支持最先的一个

生成器函数的参数传递

function * gen(args){
    console.log(args) // 'aaa'
    let one = yield 111
    console.log(one) // 'bbb'
    let two = yield 222
    console.log(two) // 'ccc'
    let three = yield 333
    console.log(three)
}
// 执行生成器函数获取迭代器对象
let iterator = gen('aaa')
console.log(iterator.next()) // {value: 111, done: false}
// next方法可以传入实参,传入的实参会作为上一个yield后返回的结果
console.log(iterator.next('bbb')) // {value: 222, done: false}
console.log(iterator.next('ccc')) // {value: 333, done: false}
console.log(iterator.next('ddd')) // {value: undefined, done: true}

生成器函数实例1:

1s后控制台输出111 --> 2s后控制台输出222 --> 3s后控制台输出333 ==> 总计耗时6s

   // 异步编程,如文件操作、网络请求、数据库操作
    // 1s后控制台输出111 --> 2s后控制台输出222 --> 3s后控制台输出333  ==> 总计耗时6s
    // 用生成器函数实现
    function one (){
        setTimeout(()=>{
            console.log(111)
            iterator.next()
        }, 1000)
    }
    function two (){
        setTimeout(()=>{
            console.log(222)
            iterator.next()
        }, 2000)
    }
    function three (){
        setTimeout(()=>{
            console.log(333)
        }, 3000)
    }
    function * gen(){
        yield one()
        yield two()
        yield three()
    }
    let iterator = gen()
    iterator.next()
    // 以下为回调地域做法
    // setTimeout(()=>{
    //     console.log(111)
    //     setTimeout(()=>{
    //         console.log(222)
    //         setTimeout(()=>{
    //             console.log(333)
    //         }, 3000)
    //     }, 2000)
    // }, 1000)

生成器函数实例2:

模拟获取 用户数据 --> 订单数据 --> 商品数据

// 模拟获取 用户数据 --> 订单数据 --> 商品数据
function getUsers(){
    setTimeout(()=>{
        let data = '用户数据'
        iterator.next(data) // 相当于把得到的数据,传回users
    }, 1000)
}
function getOrders(){
    setTimeout(()=>{
        let data = '订单数据'
        iterator.next(data)
    }, 2000)
}
function getGoods(){
    setTimeout(()=>{
        let data = '商品数据'
        iterator.next(data)
    },3000)
}
// 定义生成器函数
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()

12.Promise

Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果


Promise构造函数:Promise(excutor){}

Promise.prototype.then方法

Promise.prototype.catch方法

基本使用

// 实例化Promise对象
const p = new Promise(function(resolve, reject){
    setTimeout(()=>{
        let data = '数据库中的用户数据'
        // resolve(data)
        let err = '数据读取失败'
        reject(err)
    },1000)
})
p.then((value)=>{
    console.log('enter success')
    console.log(value)
},err=>{
    console.log('enter failed')
    console.log(err)
})

Promise封装读取文件

// 1.引入fs模块 fileSystem 文件系统
const fs = require('fs')
// 2.调用方法读取文件
// fs.readFile('./resource/file.md', (err, data)=>{ // data是一个buffer,用来存储2进制文件,用法跟数组类似
//     // 如果失败,抛出错误
//     if(err) throw err
//     // 如果成功,读取文件
//     console.log(data.toString())
// })
// 3.使用promise封装
const p = new Promise(function(resolve, reject){
    fs.readFile('./resource/file.md', (err,data)=>{
        if(err){
            reject(err)
        }else{
            resolve(data.toString())
        }
    })
})
p.then((value)=>{
    console.log(value)
},(reason)=>{
    console.error(reason)
})

Promise封装ajax

// 接口地址:https://api.apiopen.top/getJoke
// 原生ajax发送请求
// // 1.创建对象
// const xhr = new XMLHttpRequest()
// // 2.初始化
// xhr.open('GET', 'https://api.apiopen.top/getJoke')
// // 3.发送
// xhr.send()
// // 4.绑定事件
// xhr.onreadystatechange = function(){
//     // 判断阶段
//     if(xhr.readyState === 4 ){
//         // 判断响应状态码
//         if(xhr.status >= 200 && xhr.status < 300){
//             // 如果状态码为成功,打印返回结果
//             console.log(xhr.response)
//         }else{
//             // 如果失败
//             console.error(xhr.status)
//         }
//     }
// }
// promise封装发送ajax请求
const p = new Promise((resolve, reject)=>{
    const xhr = new XMLHttpRequest()
    xhr.open('GET', 'https://api.apiopen.top/getJoke')
    xhr.send()
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
            if(xhr.status >=200 && xhr.status < 300){
                resolve(xhr.response)
            }else{
                reject(xhr.status)
            }
        }
    }
})
p.then((value)=>{
    console.log(value)
},(reason)=>{
    console.log(reason)
})

Promise.prototype.then方法

then方法的返回结果,依然是一个promise对象,其状态的成功或失败,由then里的回调函数的执行结果决定


如果回调函数中返回的结果是非promise类型的属性,状态为成功,且return的结果就是该promise成功后resolve的值

注: 如果没有return,则默认返回undefined,所以状态依然为成功

如果返回的结果是promise对象,则该promise对象的状态就是then返回的promise对象的状态

如果是抛出一个值(如一个错误),则状态为失败

const p = new Promise((resolve, reject)=>{
    setTimeout(()=>{
        resolve('用户数据')
        // reject('出错啦')
    }, 1000)
})
const result = p.then((value)=>{ // p执行resolve后,状态为成功,执行第一个函数
    console.log(value )
    // 1.返回非promise对象的情况
    // return 233 // 233
    // 2.返回promise对象
    return new Promise((resolve, reject)=>{
        resolve('ok') // 状态为成功,值=ok
        // reject('error!!') // 状态为失败
    })
    // 3.抛出错误
    // throw new Error('error!!!')
},(reason)=>{ // p执行reject后,状态为失败,执行第二个函数
    console.warn(reason)
})
// then方法的返回结果,依然是一个promise对象,其状态的成功或失败,由then里的回调函数的执行结果决定
console.log(result)

then方法的这个特性,决定了then方法可以进行链式调用

const p = new Promise((resolve, reject)=>{
    setTimeout(()=>{
        resolve('用户数据')
        // reject('出错啦')
    }, 1000)
})
// 链式调用
p.then((value)={
    // ...
}).then((value)=>{
    // ...
})

通过链式调用实现按顺序读取文件

// 1.引入fs模块 fileSystem 文件系统
const fs = require('fs')
// 使用传统方式实现 读取文件1 => 读取文件2 => 读取文件3
// fs.readFile('./resource/file1.md', (err, data)=>{
//     let data1 = data.toString()
//     fs.readFile('./resource/file2.md', (err,data)=>{
//         let data2 = data.toString()
//         fs.readFile('./resource/file3.md', (err,data)=>{
//             let data3 = data.toString()
//             let data_all = {data1,data2,data3}
//             console.log(data_all)
//         })
//     })
// })
// 使用promise方式实现 读取文件1 => 读取文件2 => 读取文件3
const p = new Promise((resolve, reject)=>{
    fs.readFile('./resource/file1.md', (err,data)=>{
        resolve(data)
    })
})
p.then((value) => {
    return new Promise((resolve, reject)=>{
        fs.readFile('./resource/file2.md',(err,data)=>{
            let data_all =  {
                data1: value.toString(),
                data2: data.toString()
            }
            resolve(data_all)
        })
    })
}).then((value)=>{
    return new Promise((resolve,reject)=>{
        fs.readFile('./resource/file3.md', (err,data)=>{
            value.data3 = data.toString()
            resolve(value)
        })
    })
}).then(value=>{
    console.log(value)
    //  { data1: '# 这是文件1', data2: '# 这是文件2', data3: '# 这是文件3' }
})

Promise对象catch方法

用于指定promise对象失败的回调

const p = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        // 设置p对象的状态为失败
        reject('opps error')
    },1000)
})
// p.then((value)=>{}, (reason)=>{
//     console.error(reason)
// })
// 相当于then里面的第二个回调函数
p.catch((reason)=>{
    console.warn(reason)
})

13.set(集合)

ES6提供了新的数据结构set(集合),本质上是一个对象。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用「扩展运算符」和for...of进行遍历


集合的属性和方法

size,返回集合的元素个数

add,增加一个新元素,返回当前集合

delete,删除元素,返回Boolean值

has,检测集合中是否包含某个元素,返回Boolean值

let s = new Set(['风声','雨声','读书声','风声']) // 可以接受可迭代数据,一般传入数组
// '风声','雨声','读书声'
let size = s.size // 查看元素个数
let has = s.has('读书声') // 检测是否含该元素 true
s.add('水声') // 添加元素
s.delete('读书声') // 删除元素
let has2 = s.has('读书声') // 检测是否含该元素 false
// 遍历集合
for(let item of s){
    console.log(item)
}
s.clear() // 清空集合
console.log(s, has,has2, typeof s)

set的应用

数组去重

let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1]
// 数组去重
let result = [...new Set(arr)]
console.log(result) // [1, 2, 3, 4, 5]

求交集

let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1]
let arr2 = [4, 5, 6, 5, 6]
// 求交集
let result = [...new Set(arr)].filter(item => { // 对arr去重并进行遍历
    let s2 = new Set(arr2) // 将arr2变为元素不重复的集合
    if(s2.has(item)){ // 如果元素存在s2中
        return true
    }else{
        return false
    }
})
console.log(result) // [4, 5]
// 简化写法
let result2 = [...new Set(arr)].filter(item => new Set(arr2).has(item))
console.log(result2)

求并集

let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1]
let arr2 = [4, 5, 6, 5, 6]
// 求并集:连接两个数组 => 转为元素不重复的集合 => 转为数组
let union = [...new Set([...arr, ...arr2])]
console.log(union)
// [1, 2, 3, 4, 5, 6]

求差集

let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1]
let arr2 = [4, 5, 6, 5, 6]
// 求差集-arr对arr2求差集,即求arr里面有但是arr2里没有的元素,相当于求交集的逆运算
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)))
console.log(diff) // [1, 2, 3]

14.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','LiMing') // 键名,键值
m.set('tell',function(){
    console.log('I am LiMing ')
})
let friend = {
    school: '三中'
}
m.set(friend,['小吴','小王','小芳'])
// 删除元素
m.delete('tell')
// 获取元素
let friends = m.get(friend)
console.log(friends)
// 获取元素个数
let size = m.size
console.log(size)
// 遍历Map
for(let item of m){
    console.log('item---',item)
    // 每一个item都是一个数组,第一个元素为键,第二个元素为值
}
// 清空Map
m.clear()
console.log(m)
console.log(typeof m)
相关文章
|
7月前
|
JavaScript 前端开发 开发者
ES6的常用新特性17条
ES6,也称为ECMAScript 2015,是JavaScript语言的一个重大更新,它引入了许多新的语法特性。以下是ES6的一些主要语法
|
25天前
|
前端开发
ES6 中常用的新特性
ES6 中常用的新特性
|
4月前
|
JavaScript 前端开发
ES6新特性(一)
ES6新特性(一)
|
4月前
|
JavaScript 前端开发
ES6新特性(二)
ES6新特性(二)
|
存储 JavaScript 前端开发
ES6新特性
ES6新增特性详细内容
|
7月前
|
JavaScript 前端开发 开发者
es6的新特性
es6的新特性
57 7
|
7月前
|
前端开发
ES6 部分新特性使用
ES6 部分新特性使用
39 0
|
JavaScript 前端开发 开发者
ES6 新特性
这是每个前端开发者都应该掌握的技能。ES6是JavaScript的一个重要的版本升级,它带来了许多新特性和语法糖,让我们的代码更加简洁高效。无论你是新手还是有经验的开发者,掌握ES6都会让你的编码变得更加愉快和高效。那么,让我们开始吧!
|
Java
es6中简单常用的新特性
es6中简单常用的新特性
57 0
|
前端开发 JavaScript
es6的8条新特性总结
es6的8条新特性总结
135 0