ES6—ECMASript 6 新特性(二)

1. 迭代器

1.1 定义

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

  • ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费。
  • 原生具备 iterator 接口的数据(可用for of 遍历)
    • Array
    • Arguments
    • Set
    • Map
    • String
    • TypedArray
    • NodeList

案例:使用 next() 方法遍历原生自带 iterator 接口的数据:

// Iterator是一种新的遍历机制,可以通过next()进行一一遍历
        // (1)迭代器是一个接口,能快捷的访问数据,通过Symbol、iterator来创建迭代器,
        // 通过迭代器的next()方法获取迭代之后的结果
        //(为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署Iterator接口,就可以完成遍历操作)
        // 2. 迭代器是用于遍历数据结构的指针(数据库的游标)
// 遍历 Map
const mp = new Map();
mp.set('a', 1);
mp.set('b', 2);
mp.set('c', 3);
let iter1 = mp[Symbol.iterator]();
// next() 方法每执行一次,指针自增
console.log(iter1.next()); // { value: [ 'a', 1 ], done: false }
console.log(iter1.next()); // { value: [ 'b', 2 ], done: false }
console.log(iter1.next()); // { value: [ 'c', 3 ], done: false }
console.log(iter1.next()); // { value: undefined, done: true }
// 遍历数组
let xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
let iter2 = xiyou[Symbol.iterator]();
console.log(iter2.next()); // { value: '唐僧', done: false }
console.log(iter2.next()); // { value: '孙悟空', done: false }
console.log(iter2.next()); // { value: '猪八戒', done: false }
console.log(iter2.next()); // { value: '沙僧', done: false} 
console.log(iter2.next()); // { value: undefined, done: true}

上面的案例只是为了证明他们自带 iterator 接口,实际上直接使用 for...of 方法遍历即可(iterator 接口为 for...of)服务。例如,可以使用 for [k, v] of map 来遍历 Map 数据结构中的键和值。

const mp = new Map();
mp.set('a', 1);
mp.set('b', 2);
mp.set('c', 3);
for (let [k, v] of mp) {
    console.log(k, v);
}
/*
a 1
b 2
c 3
*/

1.2 工作原理 

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

应用场景:需要自定义遍历数据的时候,要想到迭代器。

 

1.3 自定义遍历数据

我们可以通过给数据结构添加自定义 [Symbol.iterator]() 方法来使该数据结构能够直接被遍历,从而使 for...of 能够直接遍历指定数据,达到为 for...of 服务的功能。

// 需求:遍历对象中的数组
const xiaomi = {
    uname: '小明',
    course: [ '高数', '大物', '英语', '数据库' ],
    // 通过自定义 [Symbol.iterator]() 方法
    [Symbol.iterator]() {
        // 初始指针对象指向数组第一个
        let index = 0;
        // 保存 xiaomi 的 this 值
        let _this = this;
        return {
            next: function () {
                // 不断调用 next 方法,直到指向最后一个成员
                if (index < _this.course.length) {
                    return { value: _this.course[index++], done: false };
                } else {
                    // 每调用next 方法返回一个包含value 和done 属性的对象
                    return { value: undefined, done: true };
                }
            }
        }
    }
}
// for...of直接遍历达到目的
for (let v of xiaomi) {
    console.log(v);
}

 

2. Generator 生成器函数

 2.1 生成器函数的声明和调用

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

  • * 的位置没有限制
  • 使用 function * gen()yield 可以声明一个生成器函数。生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值。
  • 每一个 yield 相当于函数的暂停标记,也可以认为是一个分隔符,每调用一次 next(),生成器函数就往下执行一段。
  • next 方法可以传递实参,作为 yield 语句的返回值
// Generator 生成器函数 可以通过yield关键字,将函数挂起,为改变执行流程提供了可能,同时为做异步编程提供了方案
        // Generator函数与普通函数区别
        // 1. function后面 函数名之有个*
        // 2. 只能在函数内部使用yield表达式,让函数挂起
        function* fn(a) {
            console.log('start');
            yield 2;
            console.log('end');
        }
        let o = fn();
        console.log(o.next());//会卡在 yield 2; 这里不在往下打印
        console.log(o.next());//再调用一次next(),才会打印 end,并且返回{value: undefined, done: true}
        // 总结:Generator 生成器函数是分段执行的,yield语句是暂停执行,而next()是恢复执行
        console.log('--------------');
        function* fun() {
            console.log('start');//start   
            // x不是 yield '2'; 的返回值,它是next() 调用 恢复当前yield() 执行传入的实参
            let x = yield '2';
            console.log('one:' + x);//one:10
            let y = yield '3';
            console.log('two:' + y);
            return x + y;
        }
        const add = fun();
        console.log(add.next());  //{value: "2", done: false},这里不用赋值,因为执行到yield '2';这里就暂停了不会继续赋值给x
        console.log(add.next(10));//就是给前面的x赋值10,   {value: "3", done: false}
        console.log(add.next(20));//就是给前面的y赋值20,   {value: 30, done: true}
        // 使用场景:为不具备Iterator接口的对象提供了遍历操作

 

 2.2 生成器函数案例

案例1:1s后输出111,2s后输出222,3s后输出333

  • 传统方式:嵌套太多,代码复杂,产生 回调地狱

    setTimeout(() => {
        console.log(111);
        setTimeout(() => {
            console.log(222);
            setTimeout(() => {
                console.log(333);
            }, 3000);
        }, 2000);
    }, 1000);
  • 生成器实现:结构简洁明了

    <script>
            function one() {
                setTimeout(() => {
                    console.log(111);
                    iter.next();
                }, 1000);
            }
            function two() {
                setTimeout(() => {
                    console.log(222);
                    iter.next();
                }, 2000);
            }
            function three() {
                setTimeout(() => {
                    console.log(333);
                    iter.next();  //个人认为这一句可有可无
                }, 3000);
            }
            function* gen() {
                yield one();
                yield two();
                yield three();
            }
            let iter = gen();
            iter.next();
        </script>

3. Promise 

3.1  Promise 的定义和使用

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

一个 Promise 必然处于以下几种状态之一:

  • 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled):意味着操作成功完成。
  • 已拒绝(rejected):意味着操作失败。

Promise 的使用:

  • Promise 构造函数:new Promise((resolve, reject)=>{})
  • Promise.prototype.then 方法
  • Promise.prototype.catch 方法
<script>
        // Promise 承诺
        // 相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果
        // 各种异步操作都可以用同样的方法进行处理 axios

        // 特点:
        // 1. 对象的状态不受外界影响,处理异步操作 三个状态 Promise(待定) fulfilled/Resolved(成功) rejected(失败)
        // 2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果
        let pro = new Promise(function (Resolved, rejected) {
            // 执行异步操作
            let res = {
                code: 200,
                data: {
                    name: 'lsy'
                },
                error: {
                    age: 18
                }
            }
            setTimeout(() => {
                if (res.code === 300) {
                    Resolved(res.data);
                } else {
                    rejected(res.error)
                }
            }, 2000)
        })
        console.log(pro);
        pro.then((val) => {
            console.log(val);//接收的是Resolved这个函数
        }, (err) => {
            console.log(err);//接收的是rejected这个函数
        })

        
    </script>

 

3.2 
 Promise 封装读取文件

 // 封装一个异步操作
        function timeOut(ms) {
            return new Promise((Resolved, rejected) => {
                setTimeout(() => {
                    console.log('成功了!');
                }, ms);
            })
        }
        timeOut(2000).then((val) => {
            console.log(val);
        })

3.3  Promise 封装 Ajax 请求(待补充

下面代码还没完善,没看懂,要重看... 

<script>
        // 自己封装的
        const getJSON = function (url) {
            return new Promise((resole, reject) => {
                const xhr = new XMLHttpRequest();
                // 第一步:打开
                xhr.open('GET', url);//方式是GET,对象是形参
                //当前状态发生改变(0-4)0初始化,1还没发送,2 3当前进行中,4成功回调
                xhr.onreadystatechange = handler;//对应的是一个回调函数
                xhr.responseType = 'json';//约定返回数据的类型为json
                xhr.setRequestHeader('Accept', 'application/json');
                // 发送
                xhr.send();//必须写
                function handler() {
                    // console.log(this);
                    if (this.readyState === 4) {
                        if (this.status === 200) {
                            resole(this.response.HeWeather6)
                        } else {
                            reject(new Error(this.statusText))
                        }
                    }
                }
            })
        }
        // 调用的
        getJSON('http://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
            .then((data) => {
                console.log(data);
            }, (err) => {
                console.log(err);
            })

        // then() 第一个参数是resole回调函数,第二个参数是可选的,是reject状态回调的函数
        // then()返回一个新的Promise实例,可以用来链式编程

        // resole() reject() all() race() done() finally()
        // 1. resole() 能将现有的任何对象转换成Promise对象
        // let p = Promise.resolve('foo');//等价于 ↓
        // let p=new Promise(resole=>resole('foo'));
        // console.log(p);//Promise {<fulfilled>: "foo"}
        // p.then((data) => {
        //     console.log(data);//foo
        // })

        // 2. all() 应用:一些游戏类的素材比较多,等待图片、flash、静态资源文件,都加载完成,才进行页面的初始化
        let p1 = new Promise((resole, reject) => { })
        let p2 = new Promise((resole, reject) => { })
        let p3 = new Promise((resole, reject) => { })
        let p4 = Promise.all([p1, p2, p3])
        p4.then(() => {
            // 三个都成功 才成功
        }).catch(err => {
            // 如果有一个失败 则失败
        })

        // 3. race() 某个异步请求设置超时时间,并且在超时后执行相应操作
        // (1)请求图片
        function requestImg(imgSrc) {
            return new Promise((resole, reject) => {
                const img = new Image();
                img.onload = function () {
                    resole(img);
                };
                img.src = imgSrc;
            });
        };
        function timeOut() {
            return new Promise((resole, reject) => {
                setTimeout(() => {
                    reject('图片请求超时');
                }, 3000)
            })
        }
        Promise.race([requestImg('images/loginbg.png').timeOut()]).then((res) => {
            console.log(res);
        }).catch(err => {
            console.log(err);
        })
    </script>

 4. async 的用法(待补充

<script>
        // Generator Promise async 1. 解决回调地域,2. 使得异步操作更加方便
        // 作用:使得异步操作更加方便 
        // 基本操作:async会返回一个Promise对象 then catch
        // async是Generator的一个语法糖
        async function fn() {
            // return await 'hello';
            let s = await 'hello';
            let data = await s.split('')
            return data;
        }
        // console.log(fn());//返回promise对象
        // 如果async函数中有多个await 那么then函数会等待所有的await指令运行完的结果,才去执行

        fn().then(v => {
            console.log(v);//["h", "e", "l", "l", "o"]
        }).catch(e => {
            console.log(e);
        })

        async function fun() {
            // throw new Error('出错了');
            await Promise.reject('出错了');
            await Promise.resolve('hello');
        }
        fun().then(v => {
            console.log(v);//["h", "e", "l", "l", "o"]
        }).catch(e => {
            console.log(e);
        })
    </script>

5. class 类 

<script>
        // es5 造类
        // function Person(name, age) {
        //     this.name = name;
        //     this.age = age;
        // }
        // Person.prototype.sayName = function () {
        //     return this.name
        // }
        // let p1 = new Person('lsy', 18);
        // console.log(p1);

        class Person {
            // 实例化的时候会立即被调用
            constructor(name, age) {
                this.name = name;
                this.age = age;
            }

        }
        Object.assign(Person.prototype, {
            sayName() {
                return this.name;
            },
            sayAge() {
                return this.age;
            }
        })
        let p1 = new Person('lsy', 18);
        console.log(p1);
    </script>

 

6. 类的继承 extends  

<script>
        // 使用关键字 extends
        class Animal {
            constructor(name, age) {
                this.name = name;
                this.age = age;
            }
            sayName() {
                return this.name;
            }
            sayAge() {
                return this.age;
            }
        }
        class Dog extends Animal {
            constructor(name, age, color) {
                super(name, age);//相当于 ↓
                // Animal.call(this,name,age);
                this.color = color;
            }
            // 子类自己的方法
            sayColor() {
                return `${this.name}有${this.age}岁了,它的颜色是${this.color}`
            }
            // 重写父类的方法
            sayName() {
                return this.name + super.sayAge + this.color;
            }
        }
        let d1 = new Dog('大黄', 3, 'yello');
        // console.log(d1.sayName());//大黄
        console.log(d1.sayColor());//大黄有3岁了,它的颜色是yello
        console.log(d1.sayName());
    </script>

7.ES6 的模块化实现

module 

<body>
    <script type="module">
        // CommonJS和AMD
        // import obj, { name, age, sayName } from './modules/index.js';
        // console.log(obj);//{foo: "foo"}   这两个obj都可以自己命名
        // console.log(name, age, sayName());//lsy 18 my name is lsy
        // import * as f from './modules/index.js';
        // console.log(f);//出来一个模块Module
        // console.log(f.default);//{foo: "foo"}
        import Person, { name, age, sayName } from './modules/index.js';
        // console.log(Person);
        const p = new Person();
        p.sayAge()
    </script>
</body>

index.js 部分

// es6模块功能主要有两个命令构成:export和import
// export 用于规定模块的对外接口,import用于输入其他模块提供的功能
// 一个模块就是独立的文件
// export const name = 'lsy';
// export const age = 18;
// export function sayName() {
//     return 'my name is lsy';
// }
// export { sayName }
// 两个写法:1. 前面 export后面跟function函数 ,(推荐)
// 2. 前面不写 export 函数外写export,但要用{}括起来 如果这样写export.sayName()会报错
const name = 'lsy';
const age = 18;
function sayName() {
    return 'my name is lsy';
}
export {
    name, age, sayName
}
// const obj = {
//     foo: 'foo'
// }
class Person {
    constructor() {

    }
    sayAge() {
        console.log('16');
    }
}
// export default obj;
export default Person;

笔记并不完善,要结合某位不知名兄弟的笔记一起看才行 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值