ES学习1~23(ECMAcript相关介绍+ECMASript 6新特性)

1 ECMAcript相关介绍

1.1 什么是ECMA

ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1994年后该组织改名为Ecma国际。

1.2 什么是ECMScript

ECMAScript是由Ecma国际通过ECMA-262标准化的脚本程序设计语言。

1.3 什么是ECMA-262

Ecma国际制定了许多标准,而ECMA-262只是其中的一个

1.4 ECMA-262历史

ECMA-262(ECMAScript)历史版本查看网址
ES学习1~23(ECMAcript相关介绍+ECMASript 6新特性)_第1张图片

1.5 谁在维护ECMA-262

TC39(Technical Committee 39)是推进ECMAScript发展的委员会。其会员都是公司(其中主要是浏览器厂商,有苹果、谷歌、微软、因特尔等)。TC39定期
召开会议,会议由会员公司的代表与特邀专家出席

1.6 为什么要学习ES6

  • ES6的版本变动内容最多,具有里程碑意义
  • ES6加入许多新的语法特性,编程实现更简单、高效
  • ES6是前端发展趋势,就业必备技能

1.7 ES6兼容性

http://kangax.github.io/compat-table/es6/可查看兼容性

2 ECMASript 6新特性

2.1 let关键字

let关键字用来声明变量,使用let声明的变量有几个特点:

  1. 不允许重复声明
  2. 块儿级作用域
  3. 不存在变量提升
  4. 不影响作用域链

应用场景:以后声明变量使用let就对了

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <script>
        // 声明变量
        let a;
        let b, c, d;
        let e = 100;
        let f = 521, g = 'iloveyou', h = [];

        // 1. 变量不能重复声明
        // let star = '刘德华';
        // let star = '张学友';
        
        // 2. 块级作用域 全局 函数 eval
        // {
        //     let girl = '刘诗诗';
        // }
        // console.log(girl);

        // 3. 不存在变量提升
        // console.log(song);
        // let song = '哈哈哈';

        // 4. 不影响作用域链
        {
            let school = 'shangguigu';
            function fn() {
                console.log(school);
            }
            fn();
        }
    script>
body>
html>

let经典案例

点击div切换颜色

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>
        .item {
            width: 100px;
            height: 50px;
            border: solid 1px rgb(42, 156, 156);
            float: left;
            margin-right: 10px;
        }
    style>
head>
<body>
    <div class="container">
        <h2 class="page-header">点击切换颜色h2>
        <div class="item">div>
        <div class="item">div>
        <div class="item">div>
    div>
    <script>
        // 获取div元素对象
        let items = document.getElementsByClassName('item');

        // 遍历并绑定事件
        for (let i = 0; i < items.length; i ++ ) {
            items[i].onclick = function() {
                // 修改当前元素的背景颜色
                items[i].style.background = 'pink';
            }
        }
    script>
body>
html>

2.2 const关键字

const关键字用来声明常量,const 声明有以下特点

  1. 声明必须赋初始值
  2. 标识符一般为大写
  3. 不允许重复声明
  4. 值不允许修改
  5. 块儿级作用域

注意:对象属性修改和数组元素变化不会出发const错误

应用场景:声明对象类型使用
const,非对象类型声明选择let

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>const 定义常量title>
head>
<body>
    <script>
        // 声明常量
        const name = 'yaya';
        // console.log(name);
        // 一定要赋初值
        // const A;
        // 2. 一般常量使用大小写(潜规则)
        // const a = 100;
        // 3. 常量的值不能修改
        // NAME = 'mmm';
        // 4. 块级作用域
        // {
        //     const PLAYER = 'UZI';
        // }
        // console.log(PLAYER);
        // 5. 对于数组和对象的元素修改,不算做对常量的修改,不会报错
        const TEAM = ['UZI', 'MXLG', 'Ming', 'Letme'];
        TEAM.push('Meiko');
        console.log(TEAM);
    script>
body>
html>

2.3 变量的解构赋值

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。

  1. 数组的解构赋值
const arr = ['张学友', '刘德华','黎明', '郭富城'];
let [zhang, Liu, Li, guo] = arr;
  1. 对象的解构赋值
const lin = {
    name: '林志颖',
    tags: ['车手', '歌手', '小旋风', '演员']
}
let {name, tags} = lin;
  1. 复杂解构
let wangfei = {
    name: ' 王菲',
    age: 18,
    songs: ['红豆''流年'' 暧昧''传奇'],
    history: [
        {name: ' 窦唯'},
        {name: '李亚鹏'},
        {name: '谢霆锋'}
    ]
};
let {songs: [one, two, three], history: [first, second, third]} = wangfei;

注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式

eg:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>变量的解构赋值title>
head>
<body>
    <script>
        // ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值 这被称为解构赋值
        // 1. 数组的解构
        // const F4 = ['小沈阳', '刘能', '赵四', '宋小宝'];
        // let [xiao, liu, zhao, song] = F4;
        // console.log(xiao);
        // console.log(liu);
        // console.log(zhao);
        // console.log(song);
        
        // 2. 对象的解构
        const zhao = {
            name: '赵本山', 
            age: '不详',
            xiaopin: function() {
                console.log('我可以演小品');
            }
        };
        // let {name, age, xiaopin} = zhao;
        // console.log(name);
        // console.log(age);
        // console.log(xiaopin);
        // xiaopin();

        let {xiaopin} = zhao;
        xiaopin();
    script>
body>
html>

2.4 模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:

  1. 字符串 中可以出现换行符
  2. 可以使用${xx}形式输出变量
// 定义字符串
let str = `
  • 沈腾
  • 玛丽
  • 魏翔
  • 艾伦
`
; // 变量拼接 let lovest = '魏翔'; let out = `${lovest}是我心目中最搞笑的演员!!`;

注意:当遇到字符串与变量拼接的情况使用模板字符串

eg:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <script>
        // ES6引入新的声明字符串的方式  [``] '' ""
        // 1. 声明
        // let str = `我也是一个字符串哦!`;
        // console.log(str, typeof str);

        // 2. 内容中可以直接出线换行符
        let str = `
  • 沈腾
  • 玛丽
  • 魏翔
  • 艾伦
`
; // 3. 变量拼接 let lovest = '魏翔'; let out = `${lovest}是我心目中最搞笑的演员!!`; console.log(out);
script> body> html>

2.5 简化对象写法

ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

let name = 'yaya';
let change = function() {
    console.log('我们可以改变你!!!');
}
const school = {
    name,
    change,
    improve() {
        console.log("我们可以提高你的技能");
    }
}

2.6 箭头函数

ES6 允许使用「箭头」 (=>)定义函数。

// 1. 通用写法
1et fn = (arg1, arg2, arg3) => {
return arg1 + arg2 + arg3;
}

箭头函数的注意点:

  1. 如果形参只有一个,则小括号可以省略
  2. 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
  3. 箭头函数this指向声明时所在作用域下this的值
  4. 箭头函数不能作为构造函数实例化
  5. 不能使用arguments
// 2.省略小括号的情况
let fn2 = num => {
    return num * 10;
};
// 3.省略花括号的情况
let fn3 = score => score * 20;
// 4. this指向声明时所在作用域中this的值
let fn4 = () => {
    console.log(this);
}
let school = {
    name: 'yaya' ,
    getName() {
        let fn5 = () => {   
            console.log(this);
        }
        fn5();
    }
};

注意:箭头函数不会更改this指向,用来指定回调函数会非常合适

箭头函数实践

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            width: 200px;
            height: 200px;
            background: #58a;
        }
    </style>
</head>
<body>
    <div id="ad"></div>
    <script>
        // 需求1 点击div 2s后颜色变成粉色
        // 获取元素
        let ad = document.getElementById('ad');
        // 绑定事件
        ad.addEventListener('click', function() {
            // let _this = this;
            // 定时器
            setTimeout(() => {
                // 修改背景颜色 this
                // _this.style.background = 'pink';
                this.style.background = 'pink';
            }, 2000);
        });
        // 需求2 从数组中返回偶数的元素
        const arr = [1, 6, 9, 10, 100, 25];
        // const result = arr.filter(function(item) {
        //     if (item % 2 === 0) {
        //         return true;
        //     } else {
        //         return false;
        //     }
        // });
        const result = arr.filter(item => item % 2 === 0);
        console.log(result);
        // 箭头函数适合与this无关的回调 定时器 数组的方法回调
        // 箭头函数不适合与this有关的回调 事件水貂 对象的方法
    </script>
</body>
</html>

2.7 ES6允许函数参数赋值初始值

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <script>
        // ES6允许给函数参数赋值初始值
        // 1. 形参初始值 具有默认值的参数 一般位置要靠后(潜规则)
        // function add(a, b, c = 10) {
        //     return a + b + c;
        // }
        // let result = add(1, 2);
        // console.log(result);

        // 2. 与解构赋值结合
        function connect({host = '127.0.0.1', username, password, port}) {
            console.log(host);
            console.log(username);
            console.log(password);
            console.log(port);
        }
        connect({
            host: 'localhost',
            username: 'root',
            password: 'root',
            port: 3306
        })
    script>
body>
html>

2.8 rest参数

ES6引入rest参数,用于获取函数的实参,用来代替arguments

// 作用与arguments类似
function add(. ..args){
    console.log(args);
}
add(1, 2, 3, 4, 5);
// rest 参数必须是最后一个形参
function minus(a,b, ...args){
    console.log(a, b, args);
}
minus(100, 1, 2, 3, 4, 5, 19);

注意: rest参数非常适合不定个数参数函数的场景

2.9 spread扩展运算符

扩展运算符(spread)也是三个点(…)它好比rest参数的逆运算,将一个数组转为逗号分隔的参数序列,对数组进行解包

// 展开数组
const tfboys = ['易烊千玺', '王源', '王俊凯'];

// 声明一个函数
function chunwan() {
    console.log(arguments);
}
chunwan(...tfboys);
// 展开对象
let skillOne = {
    q: '致命打击',
};
let skillTwo = {
    w: '勇气'
};
let skillThree = {
    e: '审判'
};
let skillFour = {
    r: '德玛西亚正义'
};
let gailun = { ...skilLOne, ...skilLTwo, ...skillThree, ...skillFour};

2.10 扩展运算符应用

eg:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>扩展运算符应用title>
head>
<body>
    <div>div>
    <div>div>
    <div>div>
    <div>div>
    <script>
        // 1. 数组的合并
        // const kuaizi = ['王太利', '肖央'];
        // const fenghuang = ['曾毅', '玲花'];
        // const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
        // const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
        // console.log(zuixuanxiaopingguo);

        // 2. 数组的克隆
        // const sanzhihua = ['E', 'G', 'M'];
        // const sanyecao = [...sanzhihua];
        // console.log(sanyecao);

        // 3. 将伪数组转换为真正的数组
        const divs = document.querySelectorAll('div');
        const divArr = [...divs];
        console.log(divArr);
    script>
body>
html>

2.11 Symbol

https://www.cnblogs.com/shenjp/p/7143706.html

2.11.1. Symbol基本使用

ES5的对象属性名都是字符串,这就很容易造成属性名的冲突,比如一个项目很庞大,又不是一个人开发 的,就有可能会造成变量名冲突,如果有一个独一无二的名字就好了,这样就能从根本上防止属性名冲突。这就是ES6引入Symbol的原因。

ES6引入的是一种新的原始数据类型Symbol,表示独一无二的,它是JavaScript的第七种数据类型。Symbol值通过Symbol函数生成,只要属性名是属于Symbol类型的,就是独一无二的,可以保证不会与其他属性名产生冲突。

Symbol特点

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

eg:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <script>
        // 创建Symbol
        let s = Symbol();
        // console.log(s, typeof s);
        let s2 = Symbol('yaya');
        let s3 = Symbol('yaya');
        // Symbol.for 创建
        let s4 = Symbol.for('yaya');
        let s5 = Symbol.for('yaya');

        // 不能与其他数据进行运算
        // let result = s + 100;
        // let result = s > 100;
        // let result = s + s;

        // USONB you are so niubility
        // u undefined
        // s string symbol
        // o object
        // n null number
        // b boolean

    script>
body>
html>

eg:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <script>
        // 向对象中添加方法 up down
        // let game = {
        //     name:'俄罗斯方块',
        //     up: function(){},
        //     down: function(){}
        // };

        // // 声明一个对象
        // let methods = {
        //     up: Symbol(),
        //     down: Symbol()
        // };

        // game[methods.up] = function() {
        //     console.log('我可以改变形状');
        // }

        // game[methods.down] = function() {
        //     console.log('我可以快速下降!!');
        // }

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

2.11.2 Symbol内置值

除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。

ES学习1~23(ECMAcript相关介绍+ECMASript 6新特性)_第2张图片

ES学习1~23(ECMAcript相关介绍+ECMASript 6新特性)_第3张图片

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Symbol内置属性title>
head>
<body>
    <script>
        // class Person {
        //     static [Symbol.hasInstance](param) {
        //         console.log(param);
        //         console.log('我被用来检测类型了');
        //         return true;
        //     }
        // }
        // let o = {};

        // console.log(o instanceof Person);

        const arr = [1, 2, 3];
        const arr2 = [4, 5, 6];
        arr2[Symbol.isConcatSpreadable] = false;
        console.log(arr.concat(arr2));
    script>
body>
html>

2.12 迭代器

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

  1. ES6 创造了一种新的遍历命令for…of循环,Iterator 接口主要供for…of消费
  2. 原生具备iterator接口的数据(可用for of遍历)
    a) Array

b) Arguments

c) Set

d) Map

e) String

f) TypedArray

g) NodeList

  1. 工作原理
  • 创建一个指针对象,指向当前数据结构的起始位置
  • 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
  • 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
  • 每调用next方法返回一个包含value和done属性的对象

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

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>迭代器title>
head>
<body>
    <script>
        // 声明一个数组
        const xiyou = ['唐僧', '孙悟空', '猪八戒', '沙僧'];

        // 使用for...of遍历数组
        // for (let v of xiyou) {
        //     console.log(v);
        // }

        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());
    script>
body>
html>

eg:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义遍历数据title>
head>
<body>
    <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>
body>
html>

2.13 生成器

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

function * gen() {
    // console.log(111);
    yield '一只没有耳朵';
    // console.log(222);
    yield '一只没有尾部';
    // console.log(333);
    yield '真奇怪';
    // console.log(444);
}

let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

代码说明:

    • 的位置没有限制
  1. 生成器函数返回的结果是迭代器对象,调用迭代器对象的next方法可以得到yield语句后的值
  2. yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次next方法,执行一段代码
  3. next方法可以传递实参,作为yield语句的返回值

eg:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>生成器函数参数title>
head>
<body>
    <script>
        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'));
    script>
body>
html>

2.13.1 生成器函数实例1

DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>生成器函数实例title>
  head>
  <body>
    <script>
      // 异步编程 文件操作 网络操作(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();
    script>
  body>
html>

2.13.2 生成器函数实例2

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>生成器函数title>
head>
<body>
    <script>
        // 模拟获取 用户数据 订单数据 商品数据
        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();
    script>
body>
html>

s() {
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();

```

你可能感兴趣的:(ES,学习,前端)