Symbol、迭代器、生成器


Symbol基本使用

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是Javascript语言的第七种数据类型,是一种类似于字符串的数据类型。

Symbol特点:

  • Symbol的值是唯一的,用来解决命名冲突的问题
  • Symbol值不能与其他数据进行运算
  • Symbol定义的对象属性不能使用for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名

创建Symbol

let s = Symbol();

let s2 = Symbol('嘿嘿嘿')
let s3 = Symbol('嘿嘿嘿')
console.log(s2===s3)  //false
//Symbol.for创建
let s4 = Symbol.for('嘿嘿嘿')
let s5 = Symbol.for('嘿嘿嘿')
console.log(s4===s5)  //true

不能与其他数据进行运算

let result = s + 100    //报错
let result = s > 100    //报错
let result = s + '100'  //报错

对象添加Symbol类型的属性

let game{//声明一个对象
let methods = {
    up:Symbol(),
    down:Symbol()
};
game[methods.up] = function(){
    console.log('我可以改变形状')
}
geme[methods.down] = function(){
    console.log('我可以下降')
}      

Symbol的内置属性

hasInstance属性

class Person{
    static [Symbol.hasInstance](param){
        console.log(param)
        console.log('我被用来检测类型了')
        return false
    }
}
let o = {}
console.log(o instanceof Person)

isConcatSpreadable属性

const arr=[1,2,3]
const arr2 = [4,5,6]
arr2[Symbol.inConcatSpreadable] = false;   //表示是否可以展开
console.log(arr.concat(arr2))

迭代器

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

  • 1.ES6创造了一种新的遍历命令for…of循环,Interator接口主要供for…of消费
  • 2.原生iterator接口的数据
    • Array
    • Arguements
    • Set
    • Map
    • String
    • TypedArray
    • NodeList
  • 工作原理
    • 创建一个指针对象,指向当前数据结构的起始位置
    • 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
    • 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
    • 每调用next方法返回一个包含value和done属性的对象
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧']
let iterator = xiyou[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())

5A42A1.png

迭代器的应用

//声明一个对象
const banji = {
    name:'终极一班',
    stus:[
        'xiaoming',
        'xiaoning',
        'xiaotian',
        'knight'
    ],
    [Symbol.interator](){
        //索引变量
        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}
                }

            }
        }
    }
}

生成器

生成器函数式ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同

声明方式

function * gen(){
    console.log('hello')
}
let iterator = gen();
//console.log(iterator)
iterator.next();

function * gen(){
    console.log(111)
    yield '嘿嘿嘿'    //yield起到函数代码的分隔符的作用  第一部分
    console.log(222)
    yield '哈哈哈'    //第二部分
    console.log(333)
    yield '哦哦哦'
    console.log(444)
}
let iterator = gen();
iterator.next();    //输出第一部分111
iterator.next();    //输出第二部分222
iterator.next();    //输出第三部分333
iterator.next();    //输出第四部分444

遍历

function * gen(){
    console.log(111)
    yield '嘿嘿嘿'    //yield起到函数代码的分隔符的作用  第一部分
    console.log(222)
    yield '哈哈哈'    //第二部分
    console.log(333)
    yield '哦哦哦'
    console.log(444)
}
for(let v of gen()){
    console.log(v);
}

生成器函数参数

function * gen(arg){
    console.log(arg)
    let one = yield 111;
    console.log(one)
    let two = yield 222;
    console.log(two)
    let three = yield 333;
    console.log(three)
}
//执行获取迭代器对象
let iterator = gen('AAA')
console.log(iterator.next())  
//next方法可以传入实参
console.log(iterator.next('BBB'))
console.log(iterator.next('CCC'))
console.log(iterator.next('DDD'))
  • 下面为输出结果

5ZCdds.png

生成器函数实例

实例一:回调地狱解决问题

//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()

实例二

//模拟获取 用户数据 订单数据 商品数据
function getUsers(){
    setTiomeout(()=>{
        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.
}
//调用生成器函数
let iterator = gen();
iterator.next();

文章作者: Daniel Lin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Daniel Lin !
  目录