ES6 ------ 基础(二)

简介: ES6 ------ 基础(二)

ES6 ------ 基础(二)

Symbol

Symbol 原始数据类型, 表示独一无二的值 。

特点:

  1. Symbol 的值是唯一的,用来解决命名冲突的问题。
  2. Symbol 值不能与其他数据进行运算。
  3. Symbol定义的对象属性不能使用 for…in 循环遍历, 但是可以使用Reflect.ownKeys来获取对象的所有键名。
  1. 1.创建 Symbol
  let s = Symbol()
  console.log(s, typeof s) //Symbol() 'symbol'
  let s2 = Symbol('ES6')
    let s3 = Symbol('ES6')
    console.log(s2 === s3); //false

注意:Symbol 函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的 Symbol 函数的返回值是不相等的。

  1. 2.Symbol.for 创建
  let s = Symbol.for('ECMAScript6')
  console.log(s, typeof s) //Symbol(ECMAScript6) 'symbol'
  let s4 = Symbol.for('ES6')
    let s5 = Symbol.for('ES6')
    console.log(s4 === s5) //true

Symbol.for() 类似单例模式,首先会在全局搜索被登记的 Symbol 中是否有该字符串参数作为名称的 Symbol 值,如果有即返回该 Symbol 值,若没有则新建并返回一个以该字符串参数为名称的 Symbol 值,并登记在全局环境中供搜索。


3.不能与其他数据进行运算且Symbol 不能转为数值)

  let s = Symbol()
    let result = s + 100
    let result2 = s + s //Uncaught TypeError: Cannot convert a Symbol value to a number

4.可以显式转为字符串

  let sym = Symbol('My symbol');
  String(sym) // 'Symbol(My symbol)'
  sym.toString() // 'Symbol(My symbol)'
  //实例属性 description,直接返回 symbol 的描述
  const s = Symbol('My symbol')
  s.description // "My symbol"

5.可以转为布尔值

  let sym = Symbol();
  Boolean(sym) // true

数据类型总结:USONB

u undefined

s string symbol

o object

n null number

b boolean

Symbol 创建对象属性

向对象中添加方法

let youxi = {
        name:'狼人杀',
        [Symbol('say')]:function(){
            console.log("我可以发言");
        },
        [Symbol('zibao')]:function(){
            console.log("我可以自爆");
        }
    }
console.log(youxi);

f6c9985114964fe9ad9828a9ff781598.png

Symbol 内置属性

  1. 1.Symbol.hasInstance:当其他对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法。
  class Person{
        static [Symbol.hasInstance](param){
            console.log(param); //{}
            console.log('我被用来检测类型');
            return true
        }
    }
    let o = {}
    console.log(o instanceof Person); //true (取决于return返回的值)
  1. 2.Symbol.isConcatSpreadable:对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat() 时,是否可以展开。
  const arr = [1,2,3]
    const arr2 = [4,5,6]
    arr2[Symbol.isConcatSpreadable] = false
    console.log(arr.concat(arr2)) //(4) [1, 2, 3, Array(3)]

迭代器

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


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


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


Array、Arguments、Set、Map、String、TypeArray、Nodelist


for…of 和 for…in 的区别:


a). for…of 循环保存的是键值

b). for…in 循环保存的是键名

    // 声明一个数组
    const xiyou = ['唐僧','孙悟空','猪八戒','沙僧']
    // 使用 for...of 遍历数组
    for(let v of xiyou){
        console.log(v); //唐僧 孙悟空 猪八戒 沙僧
    }
    // 使用 for...in 遍历数组
    for(let v in xiyou){
        console.log(v); //0 1 2 3
    }

3.工作原理:

a).创建一个指针对象,指向当前数据结构的起始位置。

b).第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员。

c).接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员

d).每调用 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());
    console.log(iterator.next());

46b435accd70462a883bc38fd098bda9.png

迭代器自定义遍历对象

Symbol.iterator 为每一个对象定义了默认的迭代器。该迭代器可以被 for...of 循环使用。

通过 for…of 使用迭代器自定义遍历对象

        const banji = {
            name:"终极一班",
            stus:[
                'xiaoming',
                'xiaohua',
                'xiaoyue',
                'xiaoyan'
            ],
            [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);
        }

4e24c02bd4684f2599a15922907e5a08.png

生成器函数

生成器其实就是一个特殊的函数。

针对于异步编程的解决方案。

  1. 1.function 后要加一个 *,输出时不是使用 console.log 而是 .next()
  function * gen(){
        console.log("Hello generator");
    }
    let iterator = gen()
    iterator.next() //输出:Hello generator
  1. 2.函数代码的分隔符 yield
  function * gen(){
        console.log(111);
        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
    //第一次调用iterator.next()打印111,以此类推。
  1. 3.for…of 输出它们
  function * gen(){
        yield '熊大';
        yield '熊二';
        yield '光头强';
    }
    let iterator = gen()
    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());
    console.log(iterator.next('BBB'));
    console.log(iterator.next('CCC'));
    console.log(iterator.next('DDD'));

9c8d546e962c4e169333875a0343d672.png

生成器函数实例

要求:1s 后控制台输出 111,再 2s 后 输出222,再 3s后输出 333

  1. 1.方法一:使用 setTimeout 实现(回调地狱)
  setTimeout(() => {
        console.log(111);
        setTimeout(()=>{
            console.log(222);
            setTimeout(()=>{
                 onsole.log(333);
            },3000)
        },2000)
    },1000)

历时 6 秒可以全部输出,但是代码缩进不断向前,不利于阅读和调试(回调地狱)。

  1. 2.方法二:使用生成器函数
    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()

生成器函数实例 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()

不积跬步无以至千里 不积小流无以成江海

相关文章
ES6----内置对象拓展
ES6----内置对象拓展
|
11月前
|
JavaScript
ES6----ES6模块化
ES6----ES6模块化
|
11月前
|
前端开发 JavaScript 数据库
|
11月前
|
前端开发
|
前端开发
ES11 ------ 新增属性
ES11 ------ 新增属性
ES11 ------ 新增属性
|
12月前
|
算法 安全 JavaScript
python---js逆向------再接再励------案例
python---js逆向------再接再励------案例
|
JavaScript 前端开发
ES6 ------ 基础(五)
ES6 ------ 基础(五)
|
网络架构
ES6 ------ 基础(一)
ES6 ------ 基础(一)
|
前端开发 JavaScript
ES6 ------ let实践案例
ES6 ------ let实践案例