Home

hogen

Follow Excellence. Success will chase you.

Home About Github Email

es6 新特性02

this 问题

普通函数:根据调用我的人 this老变

  • 所属环境:在 document.onclick 函数体中

    <script>
      document.onclick = function(){
        alert(this);//[object HTMLDocument]
      };
    </script>
    
  • 所属环境:在 setInterval定时器 函数体中

    <script>
     setInterval(function(){
        alert(this);//[object Window]
      },2000);
    </script>
    

    定时器前省略了 window.setInterval,它属于 window 浏览器

  • 所属环境:在 数组定义 函数体中

    <script>
     document.onclick = function(){
        let arr = [1,2,3,4];
        arr.a = function(){
            alert(this);//1,2,3,4
        };
        arr.a();
      };
    </script>
    

箭头函数:根据所在的环境 this恒定

  • 所属环境:在 document.onclick 函数体中,不管谁调用,都是 document

    <script>
     document.onclick = function(){
        let arr = [1,2,3,4];
        arr.a = ()=>{
            alert(this);//[object HTMLDocument]
        };
        arr.a();
    };
    </script>
    
  • 所属环境:在 window 全局域中(定时器之类的都是属于 window),不管谁调用,都是window

    <script>
        let arr = [1,2,3,4];
            arr.a = ()=>{
                alert(this);
                console.log(this);//[object Window]
            }
            arr.a();
    </script>
    

bind——给函数定死一个this

class Person{
  constructor(name, age){
    this.name=name;
    this.age=age;
    console.log(this);//Person {name: "blue", age: 18}
  }

  showName(){
    alert(this);
    alert('我叫'+this.name);
  }
  showAge(){
    alert('我'+this.age+'岁');
  }
}

let p=new Person('hogen', 18);
p.showAge();//showAge 方法的 this 值为 [object Object]
//如下做法不靠谱
document.onclick=p.showName;//showName方法的 this 值为[object HTMLDocument],弹出 '我叫undefined'
// ES6 之前的解决方法
document.onclick = function(){
    p.showName();
};
// ES6 的正确打开姿势,用 bind 来定死 this,防止变来变去
 document.onclick=p.showName.bind(p);//showName方法的 this 值为[object Object],弹出 '我叫blue'

bind 是 function 的 bind,跟面向对象无关

function show(){
    alert(`this的值是:${this}`);//this的值是:[object HTMLDocument]
   }
document.onclick = show;

function show(){
    alert(`this的值是:${this}`);//this的值是:[object Window]
   }
document.onclick = show.bind();

function show(){
    alert(`this的值是:${this}`);//this的值是:abc
   }
document.onclick = show.bind('abc');

Promise

传统异步方式+Promise写法

function ajax(url,fnSucc,fnFailed){
    //创建ajax对象
    if (window.XMLHttpRequest) {
        var oAjax = new XMLHttpRequest();
    }else{
        var oAjax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    //alert(oAjax.readyState);// 0 初始化,刚刚创建
    //连接服务器
    oAjax.open('GET',url,true);
    //alert(oAjax.readyState);// 1 已连接 

    //发送请求
    oAjax.send();

    //接受返回
    oAjax.onreadystatechange = function(){
        //alert(oAjax.readyState);// 2(已发送)、3(已接收-头)、4(已接收-body) 
        if (oAjax.readyState==4) {//读取完成
            if(oAjax.status>=200 && oAjax.status<300 || oAjax.status==304){
                if (fnSucc) {
                    fnSucc(oAjax.responseText);// 把读取的结果作为参数传给方法
                }
            }else{
                if (fnFailed) {//看看用户有没有传失败的方法过来
                    fnFailed(oAjax.status);//传给用户,可以清楚是何种原因导致失败
                }
            }
        }
    }
}

function createPromise(url) {
    return new Promise((resolve,reject)=>{
        ajax(url,function(res){
            resolve(res);//成功
        },
        function(err){
            reject(err);//拒绝
        })
    });
}
Promise.all([
        createPromise("data/11.txt"),
        createPromise("data/2.txt"),
        createPromise("data/3.txt")
    ]).then(arr=>{//多个 promis 的返回值是一个数组
        let [data1,data2,data3] = arr;
        console.log(data1);
        console.log(data2);
        console.log(data3);
        // console.log(results);
    },err=>{
        alert(`发送错误了!,错误码是${err}`);
    });

jquery+Promise写法:jquery3.2 版本后,ajax 默认返回的就是一个Promise 对象

Promise.all([
        $.ajax({url:"data/1.txt",dataType:"json"}),
        $.ajax({url:"data/2.txt",dataType:"json"})
    ]).then(arr=>{//多个 promis 的返回值是一个数组
        let [data1,data2] = arr;
        console.log(data1);
        console.log(data2);
    },err=>{
        alert(`至少一个文件读取失败,错误码是:${err.status}`);
    });

Genarator

jquery+Genarator:jquery3.2 版本后,ajax 默认返回的就是一个Promise 对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Promise</title>
    <!--引入ajax函数-->
    <script type="text/javascript" src="js/ajax.js"></script>
    <script type="text/javascript" src="js/jquery.js"></script>
    <script type="text/javascript" src="js/runner.js"></script>
    <script type="text/javascript">
        runner(function *(){
            let data1  = yield $.ajax({url:'data/1.txt',dataType:"json"});
            let data2 = yield $.ajax({url:"data/2.txt",dataType:"json"});
            let data3 = yield $.ajax({url:"data/3.txt",dataType:"json"});
            console.log(data1,data2,data3);
        });
    </script>
</head>
<body>
</body>
</html>

genarator 和 promise 的区别在于当需要在异步处理复杂逻辑适合用 genarator ,当然 genarator 本身内部是对 promise 的封装,以下为异步处理逻辑传统 ajax、promise、genarator三种写法的不同

//带逻辑-普通回调
$.ajax({url: 'getUserData', dataType: 'json', success(userData){//读取用户数据
  if(userData.type=='VIP'){//判断当前用户是否是 VIP 用户
    $.ajax({url: 'getVIPItems', dataType: 'json', success(items){
      //生成列表、显示...
    }, error(err){
      alert('错了');
    }});
  }else{
    $.ajax({url: 'getItems', dataType: 'json', success(items){
      //生成列表、显示...
    }, error(err){
      alert('错了');
    }});
  }
}, error(err){
  alert('错了');
}});

//带逻辑-Promise
Promise.all([
  $.ajax({url: 'getUserData', dataType: 'json'})
]).then(results=>{
  let userData=results[0];

  if(userData.type=='VIP'){
    Promise.all([
      $.ajax({url: 'getVIPItems', dataType: 'json'})
    ]).then(results=>{
      let items=results[0];

      //生成列表、显示...
    }, err=>{
      alert('错了');
    });
  }else{
    Promise.all([
      $.ajax({url: 'getItems', dataType: 'json'})
    ]).then(results=>{
      let items=results[0];

      //生成列表、显示...
    }, err=>{
      alert('错了');
    });
  }
}, err=>{
  alert('失败');
});

//带逻辑-generator
runner(function *(){
  let userData=yield $.ajax({url: 'getUserData', dataType: 'json'});

  if(userData.type=='VIP'){
    let items=yield $.ajax({url: 'getVIPItems', dataType: 'json'});
  }else{
    let items=yield $.ajax({url: 'getItems', dataType: 'json'});
  }

  //生成、...
});

async 和 awit

用 async 和 awit 读取数据

async function show(){
    let data1 = await $.ajax({url:'data/1.txt',dataType:'json'});
    let data2 = await $.ajax({url:'data/2.txt',dataType:'json'});
    let data3 = await $.ajax({url:'data/3.txt',dataType:'json'});
    console.log(data1,data2,data3);
}
show();

用 async 的好处是不需要依赖外部库(例如上面用到的 runner.js)
上述可以变成一个匿名函数

(async function() {
    let data1 = await $.ajax({url:'data/1.txt',dataType:'json'});
    let data2 = await $.ajax({url:'data/2.txt',dataType:'json'});
    let data3 = await $.ajax({url:'data/3.txt',dataType:'json'});
    console.log(data1,data2,data3);
})();

继续演变成一个箭头函数

(async ()=> {
    let data1 = await $.ajax({url:'data/1.txt',dataType:'json'});
    let data2 = await $.ajax({url:'data/2.txt',dataType:'json'});
    let data3 = await $.ajax({url:'data/3.txt',dataType:'json'});
    console.log(data1,data2,data3);
})();

注意 genarator 不能改写成 箭头函数

利用 async 和 await 写之前异步操作带逻辑的代码

(async ()=> {
    let data1 = await $.ajax({url:'data/1.txt',dataType:'json'});
    if (data1.a+data1.b<10) {
        let data2 = await $.ajax({url:'data/2.txt',dataType:'json'});
        console.log(data2.job,data2.salary);            
    }else{
        let data3 = await $.算ajax({url:'data/3.txt',dataType:'json'});
        console.log(data3[0].name);
    }
})();

await 错误处理

async function show(){
    try{
        let data1 = await $.ajax({url:'data/1.txt',dataType:'json'});
        let data2 = await $.ajax({url:'data/23.txt',dataType:'json'});//此处文件不存在
        let data3 = await $.ajax({url:'data/3.txt',dataType:'json'});
        console.log(data1,data2,data4);
    }catch(e){
        alert('请求数据失败');
    }
}
show();

babel 编译 js

  • 安装 node.js (最好是最新版)
  • 安装 cnpm 镜像源

    $ npm install -g cnpm --registry=https://registry.npm.taobao.org

  • cnpm init 初始化工程

  • cnpm i babel-cli -D 下载 npm 依赖(-D 等价于 -save-dev)
  • 添加 babel 编译脚本到 package.json 文件

    "scripts": {
       "start": "babel src -d build"
     },
    
  • 添加 .babelrc 文件 并加入如下内容

    {
      "presets": ["env"]
    }
    
  • npm install babel-preset-env -D下载编译需要的一些插件
  • 用 es6 语法 写一个 js 文件
  • npm run start 命令编译

hogen

2018-03-14
Home About Github Email