ES6 新特性

ES6新特性

1.变量扩展

  (1).var 的问题:可以重复声明;  无法限制修改;  没有块级作用域;

  (2).新加let: 不能重复声明;  变量—可以重新进行赋值;  块级作用域;

  (3).新加const:不能重复声明;  常量—不可以重新进行赋值;  块级作用域;

        //var a=1;
        //var a=2;
        //alert(a); //可以重复声明
            
        //let a=1;
        //let a=2;
        //alert(a);//不可以重复声明
            
        const a=1;
        const a=2;
        alert(a);//和let一样

 

  块级作用域与函数声明

 

    块级作用域有什么用?

    <script>
         window.onload=function(){
             var aBtn=document.getElementsByTagName("input");                 
             for (var i=0;i<aBtn.length;i++)
             {
                 aBtn[i].onclick=function()
                 {
                     alert(i);    
                 }
             }                 
         }                          
    </script>

    <input type="button" value="按钮1">
    <input type="button" value="按钮2">
    <input type="button" value="按钮3">
    //都会弹出3

  以前解决的办法:用密封空间:

        <script>
             window.onload=function(){
                 var aBtn=document.getElementsByTagName("input");
                 
                 for (var i=0;i<aBtn.length;i++)
                 {
                     (function(i){  //封密空间
                         aBtn[i].onclick=function()
                     {
                         alert(i);    
                     };
                     })(i);                     
                 }                 
             }                          
        </script>   
// 用一个封密空间,利用函数加了一级作用域。
var 只认函数这一层。

  现在:直接改成let即可:

        <script>
             window.onload=function(){
                 var aBtn=document.getElementsByTagName("input");                 
                 for (let i=0;i<aBtn.length;i++)  //本身就是一层作用域
                 {                 
                     aBtn[i].onclick=function()
                     {
                         alert(i);    
                     };                                          
                 }                 
             }                          
        </script>  
        <input type="button" value="按钮1">
        <input type="button" value="按钮2">
        <input type="button" value="按钮3">        
     //把var 改成 let 即可,for循环就是一个语法块。

总结:let 完全可以取代const

 

2.函数扩展

 (1)箭头函数

      window.onload=function()
      {
         alert("abc")
      }
            
       window.onload=()=>{
          alert("abc")
       }

 

  箭头函数还有有两个特性:

  • 如果只有一个参数,“()”小括号可以省;
  • 如果只有一个return, “ { } ”花括号可以省;
    /*let show=function(a){
        return a*2;
    }*/
    //可以简写成            
    let show=a=> a*2;                            
    alert(show(12))

     

 (2)函数的参数

  • 参数扩展/展开;
    1.收集剩余参数,  形式:三个点,一个任意名字 ...args
     function show(a,b,...args){
          alert(a);
          alert(b);
          alert(args);
      }
      show(1,2,3,4,5,6)
                
      //1     
      //2   
      //3,4,5,6
    注意 ...args 必须放在最后一个

    2.展开数组:展开后的效果,相当于直接数组的内容写在这儿。
      let arr1=[1,2,3];
      let arr2=[5,6,8];            
      let arr=[...arr1,...arr2];            
      //  let arr=[1,2,3,5,6,8];   相当于这么写
                
      alert(arr);
                
      //1,2,3,4,5,6,7,8

     

  • 默认参数; ——传了听你的,不传听我的
      function show(a,b=88,c=99){         
         console.log(a,b,c)
      }
            
       show(1,2)
    
      // 1,2,99

     

3.变量解构赋值

  • 左右两边结构必须一样;
  • 右边必须是个内容;
  • 声明和赋值不能分开;
     //数组:
      /*let arr=[1,2,3];            
       let a=arr[0];
       let b=arr[1];
       let c=arr[2];*/
                
      //可以写成这样
       let [a,b,c] = [1,2,3]
                
       console.log(a,b,c);   //1,2,3
      //--------------------------------------------------------------------------------------
      //json
      let {a,b,c} = {a:1,b:2,c:4}
      console.log(a,b,c);  //1,2,3

     

4.数组扩展

 添加了四个方法:map  reduce  filter  forEach

 (1)map — 映射  —  一个对一个

  let arr=[10,2,3];            
  let result=arr.map(function(item){
    //alert(item)
    return (item*2)
  })
  alert(result)    // 20,4,6

  //可以写成箭头函数
  let arr=[10,2,3];             
  let result=arr.map(item=>item*2);
  alert(result)    // 20,4,6

--------------------------------------------------------------------------------------

//在写一个应用
  let score=[90,40,58,60];
  let result=score.map(item=>item>=60?"及格":"不及格");
  alert(result)  //及格,不及格,不及格,及格

 

(2)reduce  — 汇总   — 一堆出来一个  

       // 总和 
        var arr=[88,12,20];
        
        let result=arr.reduce(function(tmp,item,index){
          //alert(tmp+','+item+","+index) 三个参数分别代表:中间结果、每次的数、下标
            return tmp+item;
        })
        alert(result)  // 120
        
        
        //求平均数
        let result =arr.reduce(function(tmp,item,index){    
          if(index!=arr.length-1)  //不是最后一次
          {
            return tmp+item;   //先求和
          }
          else
          {
            return (tmp+item)/arr.length;   //去求平均数
          }    
        })
        alert(result) // 40

 

 

(3)filter —  过滤器

  //求能被三整除的
  let arr=[88,12,20,11];
  let result=arr.filter(item=>item%3==0)
  alert(result)  //12

 

(4)forEach  —  循环(迭代)

  let arr=[12,10,44];          
  arr.forEach((item,index)=>
  { 
      alert(index+":"+item)
  });  

// 0:12
// 1:10
// 2:44

 

5.字符串扩展

  • 添加了两个新方法 :startsWith 起始,endsWith 结尾
     //startsWith 
    let str="http://www.baidu.com"; if(str.startsWith("http://")){ alert("普通网址") } else if(str.startsWith("https://")) { alert("保密网址") } else { alert("其他网址") } //普通网址

     

        //endsWith 
        let str="xxx.png";  
        if(str.endsWith("txt"))
        {
            alert("文本文件");
        }
        else if(str.endsWith("png"))
        {
            alert("图片文件");
        }
        else
        {
            alert("其他");
        }
        //图片文件        

     

  • 字符串模板:字符串连接
    1.可以把东西塞到字符串里 ${ }
    2.可以换行
        let title="标题";
        let content="内容";
        
        let str=`<div>
        <h1>${title}</h1>
        <p>${content}</p>
        </div>`;
        alert(str);
        
        //结果:
        <div>
        <h1>标题</h1>
        <p>内容</p>
        </div> 

     

6.面向对象

   之前的缺点:构造函数和类不区分

   主要变化:1.class关键字,构造器(constructor) 和类分开了;

        2.class 里直接加方法。

 

//之前的
function User(name,pass)
{
    this.name=name;
    this.pass=pass;
};
User.prototype.showName=function(){
    alert(this.name);
};
User.prototype.showPass=function(){
    alert(this.pass);
};
var Obj=new User("wy","123");
Obj.showName();
Obj.showPass();
// 结果 wy 123


//ES6
class User{
    constructor(name,pass){   //constructor 构造器
        this.name=name;
        this.pass=pass;
    }
    
    showName(){
        alert(this.name)
    }
    showPass(){
        alert(this.pass)
    }
}
var Obj=new User("wy","123");
Obj.showName();
Obj.showPass();
// 结果 wy 123

 继承:

  extends:扩展,延展

  super:超类,父类

     // 之前的继承写法
        function User(name,pass)
        {
            this.name=name;
            this.pass=pass;
        }
        
        User.prototype.ShowName=function(){
            alert(this.name);
        }
        
        User.prototype.ShowPass=function(){
            alert(this.pass);
        }
        
        function VipUser(name,pass,level)
        {
            User.call(this,name,pass);
            this.level=level;
        }
        
        VipUser.prototype=new User();
        VipUser.prototype.constructor=VipUser;  //会改变constructor指向,需要手动恢复
        
        /*for(var i in User.prototype)
        {
            VipUser.prototype[i]=User.prototype[i];
        }*/
        
        VipUser.prototype.ShowLevel=function(){
            alert(this.level)
        }
                        
        var obj=new VipUser("wy","123","3");
        obj.ShowName();
        
        obj.ShowPass();
        
        obj.ShowLevel();
        // wy
        // 123
        // 3
        
        
        //---------------------------------------------------------------------------------------------------------------
        
        //ES6
        class User{
            constructor(name,pass){
                this.name=name;
                this.pass=pass;
            }
            showName(){
                alert(this.name)
            }
            showPass(){
                alert(this.pass)
            }
        }
        
        class VipUser extends User{     //用extends
            constructor(name,pass,level){    
                super(name,pass);   //用 super 从父类上继承属性
                
                this.level=level;                                        
            }
            
            showlevel(){
                alert(this.level);
            }
        }
        
        var Obj=new VipUser("wy","123","3");
        Obj.showName();
        Obj.showPass();
        Obj.showlevel();
        // wy 
        // 123 
        //3

 

 

7.json扩展

  • 1. json 对象 新加了两个方法
     (1). json.stringify : 把json 变成字符串的方法。
      var json={a:12,b:11};            
      var str='https://www.baidu.com/path/user? 
      data='+encodeURIComponent(JSON.stringify(json));  //字符串        
      alert(str)

     (2). json.parse : 把字符串变成json。
      var str='{"a":12,"b":11,"c":"abc"}';            
      var json=JSON.parse(str);            
      console.log(json)

     

  • 2. json 简写
    (1)名字一样:名字和值(key和value)一样的 ,留一个就行;
      let a=12;
      let b=12;
                
      //var json={"a":a,"b":b,"c":"abc"};
      var json={a,b,c:"abc"};  //简写
      console.log(json)

     

    (2)方法 :有方法的 “ =function "一块删除。
    var json={
      "a":12,
      /*show:function(){
         alert(this.a)
      }*/
                    
      show(){          //简写
         alert(this.a)   
      }
    }
    json.show();

     

8.promise对象 - 消除异步操作

  官方上说是 异步编程的一种解决方案。

  有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。

 

  Promise也有一些缺点:

    首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。

    其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。

    第三,当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

 

 基本用法:

  let p=new Promise(function(resolve,reject){  //Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject。它们是两个函数
        //异步代码
        //resolve --成功了
        //reject -- 失败了
        //alert(resolve)
        
        $.ajax({        
            url:'data/arr1.txt',                    
            dataType:'json',
            success(arr){
                resolve(arr)
            },
            error(err){
                reject(err);
            }
        })
    });
    
    p.then(function(arr){   //then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为Reject时调用。
        alert("成功"+arr);
        console.log(arr)
    },function(err){
        console.log(err)
        alert("失败"+err);
    });
------------------------------------------------------------------------------------------------------------------------------------------------------------
//封装起来 就是
   function CreatPromise(url){       
       //返回出去
           return new Promise(function(resolve,reject){                     
            $.ajax({        
                url,                    
                dataType:'json',
                success(arr){
                    resolve(arr)
                },
                error(err){
                    reject(err);
                }
            })
        });       
   }
   
    //Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。                                   
    Promise.all([       //Promise.all方法接受一个数组作为参数
        CreatPromise('data/arr.txt'),
        CreatPromise('data/json.txt'),
    ]).then(function(arr){
        let [arr1,arr2]=arr;
        console.log(arr1);
        console.log(arr2);
        //alert(arr1);
        //alert(arr2);
        alert("全成功");      
    },function(err){
        console.log(err);
        alert("至少有一个失败");
    })

 

有了jquery 的promise (jquery 已经封装好了promise):

Promise.all([
    $.ajax({url:'data/arr.txt',dataType:"json"}),                                            
    $.ajax({url:'data/json.txt',dataType:"json"})                    
    ]).then(result=>{            
        let [arr,json]=result;
        alert("成功");
        console.log(arr,json);

    },err=>{
        alert("失败");
    })

 

9.generator函数

   也是一种异步编程解决方案。

   普通函数--一路到底(飞机、高铁);涉及到异步操作只能用回调的方式。

    generator函数--中间能停(出租车); 可以停,数据什么时候回来在走,适合逻辑性强的。注意不能写成箭头函数。

    promise--也是不是停;有逻辑的情况下很麻烦,适合一次读一堆数据。

 

第一个generator 函数实例:

//generator函数
  function *show(){  //多一个星号 可以单独放,可以贴function或者函数名
      alert("a");
      
      yield;   //配合generator函数使用   暂时放弃执行
      
      alert("b");
  }
  
  let genObj=show();   //创建一个generator对象(和普通函数不一样,普通函数直接调用即可)
  alert(genObj);     //Object generator
  console.log(genObj);

//
next方法 指向下一个状态
 genObj.next(); //a 

genObj.next(); //b

调用遍历器对象的next方法,使得指针移向下一个状态。
也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield语句(或return语句)为止。
换言之,Generator函数是分段执行的,yield语句是暂停执行的标记,而next方法可以恢复执行。

 

 generator 原理:

 //generator函数
  function *show(){  
      alert("a");
      
      yield;   
      
      alert("b");
  }    

  //generator原理是,把大函数切成多个小函数              
  function show_1(){
      alert("a");
  }
   function show_2(){
      alert("b");
  }              
  
  let genObj=show();   
             
  genObj.next();  //show_1
  genObj.next();  //show_2

 

  yield 是什么?

  (1)可以传参

//generator函数
  function *show(){  
      alert("a");
      
      let c=yield;   
      
      alert("b");
      alert(c);  // ——>5
  }            
  
  let genObj=show();   
             
 //给yield 传参 第一个是没用的,接收的是第二个参数
  genObj.next(12);  
  genObj.next(5);  

//5

 

 (2)可以返回

 //generator函数
  function *show(){  
      alert("a");
      
      yield 12;   
      
      alert("b");
      
      return 2;//  最后一步的过程通过return给
                     
  }            
  
  let genObj=show();   
     
  let res1=genObj.next();  //有中间结果的  
   console.log(res1);      // ->{value: 12, done: false}
  let res2=genObj.next();  //有中间结果的
//console.log(res2);    // 没有return时->{value: undefined, done: true}
  console.log(res2);      // 有return时->{value: 2, done: true}

yield语句

由于Generator函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield语句就是暂停标志。

遍历器对象的next方法的运行逻辑如下。

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

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

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

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

需要注意的是,yield语句后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行,因此等于为JavaScript提供了手动的“惰性求值”(Lazy Evaluation)的语法功能。

 

 generator 应用

generatro 搭配 runner 写更加简化。

runner.js :

function runner(_gen){
  return new Promise((resolve, reject)=>{
    var gen=_gen();

    _next();
    function _next(_last_res){
      var res=gen.next(_last_res);

      if(!res.done){
        var obj=res.value;

        if(obj.then){
          obj.then((res)=>{
            _next(res);
          }, (err)=>{
            reject(err);
          });
        }else if(typeof obj=='function'){
          if(obj.constructor.toString().startsWith('function GeneratorFunction()')){
            runner(obj).then(res=>_next(res), reject);
          }else{
            _next(obj());
          }
        }else{
          _next(obj);
        }
      }else{
        resolve(res.value);
      }
    }
  });
}

generator :

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);
})

 

 

总结:

2015年6月正式发布的ECMAScript 6.0(简称 ES6)是 JavaScript 语言的下一代标准,它越来越向后台化发展。

兼容:IE10+、chrome、FireFox、移动端、NodeJs。

要兼容:(1)提前编译

    (2)在线转换 :引一个browser.js  <scirpt type="text/babel">



  

posted @ 2018-08-06 18:12  sunwy927  阅读(244)  评论(0编辑  收藏  举报