ES6(三):Iterator、Generator、类的用法、类的继承

一、迭代器Iterator

迭代器是访问数据的一个接口,是用于遍历数据结构的一个指针,迭代器就是遍历器

const items=['one','two','three'];
    //创建新的迭代器
    const it=items[Symbol.iterator]();
    console.log(it.next());

done:返回false表示遍历继续,返回true表示遍历完成

二、生成器Generator

1.generator

generator函数可以通过yield关键字将函数挂起来(只能在函数内部使用)。

它跟普通函数的区别是,他得在function后面加*,调用该函数将会返回一个遍历器对象

generator函数是分段执行的,遇到yield就暂停执行,而next()是恢复执行,把你上一个结果给你返回出来

function* func(){
        console.log('start');
        const x=yield '2';
        console.log('continue'+x);
        const y=yield '3';
        console.log('continue'+y);
        console.log(x+y);
        return x+y;
    }
    const fn=func();
    console.log(fn.next());
    console.log(fn.next(2));
    console.log(fn.next(3));
    console.log(fn.next());

x它不是yield的返回值,它是当next调用,恢复当前yield传入的实参

(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。

(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。

(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。

(4)如果该函数没有return语句,则返回的对象的value属性值为undefined。

所以遇到第一个next的时候,start先输出,然后直接到了第一个yield 2,直接输出2

第二个next,传入了实参2,被x接收,输出continue2,又遇到了yield,直接输出后面的3

第三个next,传入了实参3,被y接收,后面输出x加y为5,然后直接ruturn了5(ruturn输出的效果和yield一样{}

最后的next后面都没有东西了,输出undefined done完成

function* foo(x) {
    var y = 2 * (yield (x + 1));
    var z = yield (y / 3);
    return (x + y + z);
}

var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}  
a.next() // Object{value:NaN, done:true}   

var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false } 
b.next(13) // { value:42, done:true } 

再来一个例子,就是每次返回的时候都是yield后面的值,传参数的时候都是给上一个yield,比如说y=2*yield、、、,传12的时候就是2*12

再比如传13的时候就是z=yield、、、,就是z=13

function* dataConsumer() {
  console.log('Started');
  console.log(`1. ${yield}`);
  console.log(`2. ${yield}`);
  return 'result';
}

let genObj = dataConsumer();
genObj.next();
// Started
genObj.next('a')
// 1. a
genObj.next('b')
// 2. b

yield每次后面都没有值,所以没有返回{}啥的

2.使用场景:

(1)为不具备iterator 接口的对象提供遍历操作

之前说有Symbol.iterator接口的就可以进行遍历,那么没有这个接口的怎么进行遍历呢?

function* func(obj){//来构建一个让它有接口用
            const ks=Object.keys(obj);
            //获取对象当中所有的k保存到数组[name,age]
             for(const k of ks){
                 yield [k,obj[ks]];
             }

        }
    const obj={
        name:'ttt',
        age:18
    }//这个对象就是一个没有iterator接口的对象
    obj[Symbol.iterator]=func;
    console.log(obj);

   
    for (let [key, value] of o[Symbol.iterator](o)) {  
    console.log(`${key}:${value}`); //name:ttt   age:18
} 

以上代码可以让一个没有iterator接口的对象实现遍历

弹幕说学了ajax再来看,先放一下之后再回来看

(2)让异步代码同步化

定义三个函数:加载中、加载完成、界面隐藏

如果直接调用的话,页面加载完成会最后出现,因为它是个异步

用yield将showData函数卡住,进行showData,然后在showData加了个next去输出。

function loadUI() {
    console.log('页面加载中Loading......');
}

function showData() {
    setTimeout(() => {
        console.log('页面加载完成');
        genLoad.next();  //2.页面加载完成后就立即隐藏
    }, 1000);
}

function hideUI() {
     console.log('页面隐藏啦');
}

function* load() {
    loadUI();
    yield showData();
    hideUI();
}

let genLoad = load();
genLoad.next();  //1.加载页面,加载完成的时候停止

三、类的用法

promise和async打算学完ajax之后再返回来好好总结,先不往脑子里灌了

class Sum
       {
           constructor(x,y)
           {
               this.x=x;
               this.y=y;
           }
           add(){
               console.log(this.x+this.y) ;
           }
       }
       var a=new Sum(1,4);
       a.add();

类似java写法,class封装一个类,constructor()方法是默认加进去的,不写也默认会有,通过new生成对象实例的时候会自动调用这个方法。

add()函数前面不需要再加function。

四、类的继承

class Animal
       {
           constructor(name,age)
           {
               this.name=name;
               this.age=age;
           }
           sayName(){
               return this.name;
           }
           sayAge(){
               return this.age;
           }
       }

有一个animal的类,我还想写一个dog类,包括名字年龄和颜色,其中年龄和颜色Animal都有,咱们就可以直接继承过来

class Dog extends Animal{
           constructor(name,age,color)
           {
               super(name,age);//要继承的
               this.color=color;
           }
       }
       let t=new Dog('hh',2,'yellow');
       console.log(t);
       console.log(t.sayAge());//2

不仅可以继承属性,还能继承方法

class Dog extends Animal{//extends继承
           constructor(name,age,color)
           {
               super(name,age);//super使用继承来的方法
               this.color=color;
           }
           sayColor(){//自己的方法
               return `${this.age}是${this.name}`;
           }
           //重写父亲的方法
           sayName(){
               return super.sayName();
           }

       }
       let t=new Dog('hh',2,'yellow');
       console.log(t.sayAge());//2
       console.log(t.sayColor());
       console.log(t.sayName());
相关推荐
八了个戒几秒前
【TypeScript入坑】什么是TypeScript?
开发语言·前端·javascript·面试·typescript
不悔哥13 分钟前
vue 案例使用
前端·javascript·vue.js
anyup_前端梦工厂44 分钟前
Vuex 入门与实战
前端·javascript·vue.js
你挚爱的强哥1 小时前
【sgCreateCallAPIFunctionParam】自定义小工具:敏捷开发→调用接口方法参数生成工具
前端·javascript·vue.js
喝旺仔la1 小时前
Element 表格相关操作
javascript·vue.js·elementui
米老鼠的摩托车日记2 小时前
【vue element-ui】关于删除按钮的提示框,可一键复制
前端·javascript·vue.js
forwardMyLife2 小时前
element-plus的菜单组件el-menu
javascript·vue.js·elementui
猿饵块2 小时前
cmake--get_filename_component
java·前端·c++
好多吃的啊2 小时前
背景图鼠标放上去切换图片过渡效果
开发语言·javascript·ecmascript
大表哥62 小时前
在react中 使用redux
前端·react.js·前端框架