ES6学习笔记(第二讲)

一、单体模式下的对象

以前咱们定义一个对象,使用的语法格式以下所示:html

<script>
        var name = 'qianqian';
        var age = 24;
        var person = {
            name:name,
            age:age,
            showName:function(){
                console.log(this.name);
            }
        };
        person.showName();
    </script>

在ES6当中声明定义一个对象的语法简洁化了。在ES6的对象语法当中,若是对象的属性名和属性值变量名相同,则只使用一个变量名便可,即便用name来代替name:name的写法。对象的方法定义能够从方法名:function(){}改成方法名(){}的写法。ES6当中单体模式下对象声明的语法格式以下所示:前端

<script>
        let name = 'qianqian';
        let age = 24;
        let person = {
            name,
            age,
            showName(){
                console.log(this.name);
            }
        };
        person.showName();
    </script>

这两种写法的运行结果相同,均为输出qianqiannode

二、面向对象(class 和 constructor)

以前在面向对象当中类和构造函数的概念区分并不明显。示例代码以下所示:jquery

<script>
        //定义一个构造函数(类),在里面定义类的属性
        function Person(name,age){
            this.name = name;
            this.age = age;
        };
        //使用prototype定义类的方法
        Person.prototype.showName = function(){
            console.log(this.name);
        };
        //使用new来调用声明好的类,传入不一样的实参来造成不一样的实例对象。
        var p1 = new Person('qianqian',24);
        p1.showName();
    </script>

在ES6当中,类(class)和构造函数(constructor)的概念被区分开了。ES6当中使用面向对象的语法来定义一个类的示例代码以下所示:git

<script>
        //使用关键字class来定义一个Person类,在内部定义其属性与方法
        class Person{
            //在构造函数当中定义类的属性
            constructor(name,age){
                this.name = name;
                this.age = age;
            };
            //接下去分别定义类的方法,不须要再使用prototype
            showName(){
                console.log(this.name);
            };
        };
        //使用new来调用声明好的类,传入不一样的实参,来生成不一样的实例对象
        let p1 = new Person('qianqian',24);
        p1.showName();
    </script>

Person这个类生成的实例对象,都有一个默认的constructor属性,其属性值均为类名Person。示例代码以下所示:github

<script>
        class Person{
            constructor(name,age){
                this.name = name;
                this.age = age;
            };
            showName(){
                console.log(this.name);
            };
        };
        let p1 = new Person('qianqian',24);
        let p2 = new Person('meimei',23);
        console.log(p1.constructor == Person);
        console.log(p2.constructor == Person);
        console.log(p1.showName == p2.showName);
    </script>

其输出结果均为trueajax

三、原型继承

假设有一个子类Worker类要继承父类Person类,在以前的面向对象的语法当中,咱们在Worker类的构造函数当中,使用Person.apply(this,arguments);来完成对父类属性的继承。使用Worker.prototype = new Person();来实现对父类方法的继承。示例代码以下所示:json

<script>
        function Person(name,age){
            this.name = name;
            this.age = age;
        };
        Person.prototype.showName = function(){
            console.log(this.name);
        };
        function Worker(name,age){
            Person.apply(this,arguments);
        };
        //实现方法继承的语法格式为:子类.prototype = new 父类();
        Worker.prototype = new Person();
        //完成继承后,使用Worker类来生成实例
        var w1 = new Worker('qianqian',24);
        w1.showName();
    </script>

输出结果为qianqianbootstrap

apply方法只接收两个参数,其中第二个参数必须是一个数组或者类数组,故能够将当前函数的arguments对象做为apply函数的第二个参数传入。apply方法改变的是函数的调用对象,此方法的第一个参数为改变后调用这个函数的对象。数组

而在ES6当中,实现原型继承的语法就相对简化了许多,咱们使用class 子类 extends 父类{};便可完成子类继承父类所有属性和方法的功能。咱们能够给继承的子类对象随意添加新的方法,但若是想要给子类添加新的属性,在其构造函数的内部,使用super(父类的形参列表);先调用一次父类的构造函数,避免覆盖父类的构造函数,而后再定义新的子类属性。示例代码以下所示:

<script>
        class Person{
            constructor(name,age){
                this.name = name;
                this.age = age;
            };
            showName(){
                console.log(this.name);
            };
        };
        class Worker extends Person{
            constructor(name,age,job){
                //至关于先调用一次父类的构造函数,防止覆盖父类的构造函数
                super(name,age);
                //再定义新的子类属性
                this.job = job;
            };
            //能够随意给子类对象添加新的方法
            showName(){
                console.log(this.name);
            };
            showJob(){
                console.log(this.job);
            };
        };
        //调用子类生成实例对象
        let w1 = new Worker('qianqian',24,'student');
        w1.showName();
        w1.showJob();
    </script>

输出结果为qianqianstudent

四、模块化

ES6自带模块化,不过咱们在使用ES6的这个新语法特性时,必须引入编译文件,由于浏览器端尚未彻底支持。好比咱们定义一个模块a.js(通常一个js文件即表明一个模块),在其内部定义了变量和函数以后,可使用export default {变量名,函数名};的方式来导出。a.js的示例代码以下所示:

let a = 5;
function sum(){
    return 'haha';
};
export default {a,sum};

咱们在主文件index.html当中使用import 自定义模块名 from '模块文件的相对路径';来实现模块的导入。其中index.html的示例代码以下所示:

<script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
    <script src="https://google.github.io/traceur-compiler/bin/BrowserSystem.js"></script>
    <script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script>
    <script type="module">  
        import A from './a.js';
        console.log(A.a);
        console.log(A.sum());
    </script>

若第一次运行报以下错误:

图片描述

是由于咱们没有把项目文件放在服务器环境下运行。

输出结果为5haha

五、Promise 对象

promise是ES6当中一个新的语法点,这个对象主要用来传递和处理异步操做的数据。promise对象只有三种状态:pending(等待)、resolve(成功)、reject(失败),而且其状态变化只能是从pendingresolve,或者是从pendingreject。其基本使用语法的示例代码以下所示:

<script>  
        //通常在异步操做回调函数当中,声明一个Promise对象
        let p1 = new Promise(function(resolve,reject){
            if(异步操做成功){
                resolve(成功的数据);
                //把成功的数据传递下去
            }else{
                reject(失败的缘由);
                //把失败的缘由传递下去
            };
        });
        //promise对象p1具备then方法,接收两个函数参数,该方法仍然返回promise对象
        p1.then(function(value){
            /*当p1的回调函数当中执行resolve(成功的数据)时,执行该函数,形参value接收由resolve传递下来的成功的数据。*/
        },function(err){
            /*当p1的回调函数当中执行reject(失败的缘由)时,执行该函数,形参err接收由reject传递下来的失败的缘由。*/
        });
    </script>

咱们在前端使用ajax异步操做数据时,可使用promise对象,示例代码以下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="jquery-1.10.2.js"></script>
    <script>  
       $(function(){
               $('#btn').on('click',function(){
                   let p1 = new Promise(function(resolve,reject){
                       $.ajax({
                           url:'http://localhost/demo/1.txt',
                           type:'GET',
                           dataType:'text',
                           success:function(data){
                               resolve(data);
                           },
                           error:function(){
                               reject('failed');
                           }
                       });
                   });
                   p1.then(function(value){
                       console.log(value);
                   },function(err){
                       console.log(err);
                   });
               });
       });
    </script>  
</head>
<body>
    <button id="btn">button</button>
</body>
</html>

咱们也能够在node.js的异步操做的回调函数当中使用promise对象。示例代码以下所示:

'use strict';
const fs = require('fs');
const path = require('path');
let target = path.join(__dirname,'./1.txt');
fs.readFile(target,function(err,data){
    let p1 = new Promise(function(resolve,reject){
        if(err){
            reject(err);
        }else{
            resolve(data);
        };
    });
    p1.then(function(data){
        console.log(data.toString());
    },function(err){
        console.log(err);
    });
});
5.一、promise对象的方法

一、 .then()

该方法在前面有详细介绍,其示例代码以下所示:

<script>  
     let p1 = new Promise(function(resolve,reject){
         resolve(1);
     });
     p1.then(function(value){
         alert(value);
         return value + 1;
     },function(value){
         alert(value);
         return value + 2;
     }).then(function(value){
         alert(value);
     });
</script>

先弹出1,再弹出2

二、.catch()

该方法用于捕获异常信息。其示例代码以下所示:

<script>  
         let p1 = new Promise(function(resolve,reject){
             resolve(1);
         });
         p1.then(function(value){
             throw value;
         }).catch(function(e){
             alert(e);
         });
    </script>

输出结果为弹出数字1

5.二、Promise类身上的方法

一、 Promise.resolve()

这个方法能够生成一个成功的promise对象。该方法的参数能够是一个单纯的值或数组,也能够是另外一个promise的执行结果。示例代码以下所示:

<script>  
         let p1 = Promise.resolve([1,2,3]);
         p1.then(function(value){
             console.log(value[2]);
         },function(err){
             alert('failed');
         });
    </script>

输出结果为3

二、 Promise.reject()

这个方法能够生成一个失败的promise对象。示例代码以下所示:

<script>  
         let p1 = Promise.reject('failed');
         p1.then(function(value){
             alert('success')
         },function(err){
             alert(err);
         });
    </script>

弹出结果为'failed'

三、 Promise.all()

该方法默认接收一个数组,其中数组元素均为promise对象。这个方法能够将多个promise对象组合,包装成一个全新的promise对象。

这个全新的promise对象也有then方法,当其参数当中全部的promise对象都成功时,才会执行then方法当中的第一个参数函数,此时该函数的形参表明一个数组,里面的值按顺序出现。示例代码以下所示:

<script>  
         let p1 = Promise.resolve(1);
         let p2 = Promise.resolve(2);
         let p3 = Promise.resolve(3);
         Promise.all([p1,p2,p3]).then(function(value){
             console.log(value);
         },function(err){
             console.log('failed');
         });
    </script>

其输出结果为[1,2,3]

在其参数数组当中只要出现失败的promise对象,就会执行then方法当中的第二个参数函数,形参仅包含最早出现的那个失败的promise对象当中的值。示例代码以下所示:

<script>  
         let p1 = Promise.resolve(1);
         let p2 = Promise.reject(2);
         let p3 = Promise.reject(3);
         Promise.all([p1,p2,p3]).then(function(value){
             console.log('success' + value);
         },function(err){
             console.log('failed' + err);
         });
    </script>

其输出结果为'failed2'

四、 Promise.race()

该方法默认接收一个数组,其中数组元素均为promise对象。这个方法选取最早到达的那个promise结果,该方法的返回结果也为一个promise对象。示例代码以下所示:

<script>  
         let p1 = new Promise(function(resolve,reject){
             setTimeout(resolve('one'),50);
         });
         let p2 = new Promise(function(resolve,reject){
             setTimeout(resolve('two'),100);
         });
         Promise.race([p1,p2]).then(function(value){
             console.log(value);
         },function(err){
             console.log(err);
         });
    </script>

其输出结果为'one'

六、Generator(生成器)

生成函数与普通函数在语法格式上的区别为,在函数名前面有*号,通常紧跟在function的后面。在生成器函数的内部,有一种相似与return的语法,关键字yieldyield语句能够用于遍历函数内部的状态)。两者的区别是,普通函数只能return一次,而生成器函数能够yield屡次。在生成器函数的执行的过程当中,遇到yield表达式当即暂停,后续能够恢复执行状态。示例代码以下所示:

<script> 
        //声明一个生成器函数show 
         function* show(){
             yield 'hello';
             yield 'world';
             yield 'ES6';
             return 'all';
         };
         //生成器函数先调用一次,用变量res来接收该函数执行的返回值
         let res = show();
         /*这个返回值身上自带方法.next(),相似于开始进行状态遍历,该方法每调用一次,都会返回一个对象,有value和done这两个属性,value的属性值为每次yield后面对应的值,done的属性值是一个布尔值,表明状态遍历是否结束。*/
         console.log(res.next());
         console.log(res.next());
         console.log(res.next());
         console.log(res.next());
         console.log(res.next());
    </script>

其输出结果为:

图片描述

生成器函数能够放在对象内部,做为对象的一个方法。其示例代码以下所示:

<script> 
        var json1 = {
            *show(){
                yield 'hello';
                yield 'world';
                return 'all';
            }
        };
        var json2 = {
            show:function*(){
                yield 'xixi';
                yield 'haha';
                return 'so';
            }
        };
        var res1 = json1.show();
        console.log(res1.next());
        console.log(res1.next());
        console.log(res1.next());
        var res2 = json2.show();
        console.log(res2.next());
        console.log(res2.next());
        console.log(res2.next());
    </script>

其输出结果为:

图片描述

咱们可使用for...of来循环生成器函数,示例代码以下所示:

<script> 
        function* show(){
            yield 'hello';
            yield 'world';
            yield 'ES6';
            return 'all';
        };
        for(let v of show()){
            console.log(v);
        };
    </script>

其输出结果为:

图片描述

生成器函数的yield表达式语句自己没有返回值,或者说老是返回undefinednext()方法能够带一个参数,该参数会被当作上一条yield语句的返回值。示例代码以下所示:

<script> 
        function* show1(){
            let a = yield 'hello';
            return a;
        };
        let res1 = show1();
        console.log(res1.next());
        console.log(res1.next());
        function* show2(){
            let a = yield 'hello';
            return a;
        };
        let res2 = show2();
        console.log(res2.next());
        console.log(res2.next('world'));
        function* show3(){
            for(let i = 0; i < 10; i++){
                let a = yield i;
                if(a){
                    i = -1;
                };
            };
        };
        let res3 = show3();
        console.log(res3.next());
        console.log(res3.next());
        console.log(res3.next(true));
        console.log(res3.next());
    </script>

其输出结果为:

图片描述

相关文章
相关标签/搜索