ECMASCript6 新特性介绍

版权声明:本文为博主原创文章,转载请告知我,您的转载是对我最大的鼓励。 https://blog.csdn.net/wkl115211/article/details/82314338

一、介绍

1.历史

  1. ECMAScript和JavaScript

    • ECMAScrip是标准,JavaScript是实现
      • 类似于HTML5是标准,IE10、Chrome、FF都是实现
      • 换句话说,将来也能有其他XXXScript来实现ECMA
    • ECMAScript简称ECMA或ES
    • 目前版本
      • 低级浏览器主要支持ES 3.1
      • 高级浏览器正在从ES 5过渡到ES 6
  2. 历史版本

时间 ECMA JS 解释
1996.11 ES 1.0 JS稳定 Netscape将JS提交给ECMA组织,ES正式出现
1998.06 ES 2.0 ES2正式发布
1999.12 ES 3.0 ES3被广泛支持
2007.10 ES 4.0 ES4过于激进,被废了
2008.07 ES 3.1 4.0退化为严重缩水版的3.1
因为吵得太厉害,所以ES 3.1代号为Harmony(和谐)
2009.12 ES 5.0 ES 5.0正式发布
同时公布了JavaScript.next也就是后来的ES 6.0
2011.06 ES 5.1 ES 5.1成为了ISO国际标准
2013.03 ES 6.0 ES 6.0草案定稿
2013.12 ES 6.0 ES 6.0草案发布
2015.06 ES 6.0 ES 6.0预计发布正式版
JavaScript.next开始指向ES 7.0

2.兼容性

1.兼容性

2.编译与转换,将ES6编译转换成低版本浏览器支持的JS代码

  • 在线编译,使用语法解析转换工具将ES6语法解析转换为大部分浏览器识别的ES5语法,通用的转换方案有babel,traceur,jsx,typescript,es6-shim,其中,Bable是比较常用的,参见Bable,可以引入browser.js使浏览器支持Babel;
  • 提前编译

2.ES6特性

1.变量

1.var的缺陷

  • 可以重复声明,var a =5; var b = 7; var a = 12;
  • 无法限制修改,对于某些常量,如PI等可以任意修改;
  • 没有块级作用域,var作用于函数,而不是作用于块语句;

2.新的关键字

  • let: 不能重复声明,变量可以修改,块级作用域
  • const: 不能重复声明,变量不可以修改,块级作用域
var aBtn = document.getElementByTagName('button');
(function(i){
    for(var i = 0; i < aBtn.length; i++){
    aBtn.i.onclock = function(){
        alert(i);
}
})(i)
}

用let不用闭包来解决以上问题:

var aBtn = document.getElementByTagName('button');
for(var let = 0; i < aBtn.length; i++){
    aBtn.i.onclock = function(){
        alert(i);
    }
}

2.函数

1.箭头函数

省略条件

  • 如果只有一个参数,()可以省略;
  • 如果只有一个return语句,{}可以省略
let show = function(){
    alert('13')  
}
show();
let show = ()=>{
    alert('13')
}
function add(a, b){
    return a+b
}
add(5,12);
(a, b)=>a+b

2.函数参数

1.参数扩展/数组展开

  • 参数扩展:…args,用来收集剩余参数,但必须是参数列的最后一个,例如:
function add(a, b, ...args){
    return a+b;
};
add(1,2,3,4,4,6);//函数中的3,4,4,6会传给...args;
  • 数组展开。
let arr = [1,2,3] ...arr//1,2,3  
let arr1 = [2,3], arr2 = [e,3]; 
let arr3=[...arr1, ...arr2]; arr3//2, 3, e, 3

2.默认参数, 参数默认值 function(a, b=2){};

3.解构赋值,直接对多个变量同时赋值,解构赋值条件如下:

  • 左右两边结构一样
  • 右边必须符合语法
  • 声明和赋值不能分开

使用场景
解构赋值在很多时候可以大大简化代码。例如,交换两个变量x和y的值,可以这么写,不再需要临时变量:

var x=1, y=2;
[x, y] = [y, x]

快速获取当前页面的域名和路径:

var {hostname:domain, pathname:path} = location;

如果一个函数接收一个对象作为参数,那么,可以使用解构直接把对象的属性绑定到变量中。例如,下面的函数可以快速创建一个Date对象:

function buildDate({year, month, day, hour=0, minute=0, second=0}) {
    return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);
}  

它的方便之处在于传入的对象只需要year、month和day这三个属性:

buildDate({ year: 2017, month: 1, day: 1 });
// Sun Jan 01 2017 00:00:00 GMT+0800 (CST)

也可以传入hour、minute和second属性:

buildDate({ year: 2017, month: 1, day: 1, hour: 20, minute: 15 });
// Sun Jan 01 2017 20:15:00 GMT+0800 (CST)

3.数组

新增加了四个函数,分别是:

  • map 映射 返回长度和原数组相同的数组 arr.map(function(item, index, arr))
  • reduce 汇总 arr.reduce(function(tmp, item, index)) tmp为计算得到的临时值
  • filtr 过滤 arr.filter(function(item, index, arr))
  • forEach 循环 arr.forEach(function(item, index){})
let arr1 = [12, 23, 15];
let result = arr1.map(item=>item);
alert(result);

let result2 = arr1.reduce((tmp, item, index) => {
    if(index != arr1.length-1){
      return tmp+item
    } else {
      return (tmp+item)/arr1.length
    }
});

arr1.forEach((item, index) => {
    console.log(index + ':' + item)
});

3.字符串

1.多了两个新方法,感觉像是根据正则表达式封装实现的

  • startsWith(str) 判断字符是否以str开头;
  • endsWith(str) 判断字符是否以str结尾;

2.字符串模板

  • 字符串中可以识别变量 $(变量);
  • 可以换行;
let firstname = 'bill';
let lastname = 'gates';
let name = `${firstname}, ${lastname}`;

4.面向对象

ES5中实现面向对象的继承需使用原型链,具体如下:

function Person(props){
    this.name = props.name;
    this.age = props.age;
}

Person.prototype.getName = function(){
    return this.name;
}

function Student(props){
    Person.call(this, props);
    this.school = props.school;
}

Student.prototype = new Person();
Student.prototype.constructor = Student;

出现class, super, extends等面向对象关键字后,便可以使用类似JAVA的方式实现继承,但是实质上是对原型和原型继承的封装,class等关键字只是语法糖,还是要理解原型和原型链等。使用class等关键字如下:

class User{
    constructor(name, pass){
        this.name = name
        this.pass = pass
    }

    showName(){
        alert(this.name)
    }

    showPass(){
        alert(this.pass)
    }
}
class VipUser extends User{
    constructor(name, pass, level){
        super(name, pass)
        this.level = level
    }

    showLevel(){
        alert(this.level)
    }
}

let vl = new VipUser('hotsuitor', '123456', 5)

v1.showName()
v1.showPass()
v1.showLevel()

4.JSON

JSON是JavaScript Object Notation的缩写,它是一种数据交换格式,由道格拉斯·克罗克福特(Douglas Crockford)设计,JSON实际上是JavaScript的一个子集。JSON还定死了字符集必须是UTF-8,表示多语言就没有问题了。为了统一解析,JSON的字符串规定必须用双引号”“,Object的键也必须用双引号”“。在JSON中,数据类型:

  • number:和JavaScript的number完全一致;
  • boolean:就是JavaScript的true或false;
  • string:就是JavaScript的string;
  • null:就是JavaScript的null;
  • array:就是JavaScript的Array表示方式——[];
  • object:就是JavaScript的{ … }表示方式。

1.JSON对象,两个方法:

  • stringfiy() 序列化;
  • parse() 反序列化;
var xm = {
    name: '小明',
    age: 14,
    toJSON: function () {
        return { // 只输出name和age,并且改变了key:
            'Name': this.name,
            'Age': this.age
        };
    }
};

JSON.stringify(xm);

JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}

2.JSON简写

  • 名字和值一样
  • 方法可以省略function关键字
let a=12,b=12;
let json={a,b,c:12} == {a:a,b:b,c:12}

let json = {
    a:12,
    show(){
        alert(this.a);
    }
}

5.Promise

1.什么是Promise

是JS异步编程的重要概念,异步抽象处理对象,是目前比较流行的JS异步编程解决方案之一

2.异步编程方案

异步编程方案有以下几种,具体后面会有文章来详细介绍:

  • 回调函数
  • 事件监听
  • 发布/订阅模式
  • Promise
  • Generator

3.Promise

Promise 是一个构造函数, new Promise 返回一个 promise对象 接收一个excutor执行函数作为参数, excutor有两个函数类型形参resolve reject。
promise相当于一个状态,有三种状态,并且promsie状态只能由 pending => fulfilled/rejected, 一旦修改就不能再变:

  • pending promise对象的初始状态
  • fulfilled 调用resolve(success) 会由pending => fulfilled
  • rejected 调用resolve(error) 会由pending => rejected

4.Promise方法

  • then方法注册 当resolve(成功)/reject(失败)的回调函数,异步执行;
  • resolve(成功) onFulfilled会被调用;
  • reject(失败) onRejected会被调用;
  • Promise.resolve 返回一个fulfilled状态的promise对象;
  • Promise.reject 返回一个rejected状态的promise对象;
  • Promise.all 接收一个promise对象数组为参数,只有全部为resolve才会调用,通常会用来处理多个并行异步操作;
  • Promise.race 接收一个promise对象数组为参数,Promise.race 只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理。

5.Promise原理

Promise像是一个状态机,分为初始状态、成功和失败状态。Promoise的构造函数接受一个函数fn作为参数,fn有两个参数函数:参数resolve和reject,因为Promise是一个状态机,需要声明一个属性记录其状态,同时,需要声明两个属性记录返回数据,then方法接受两个函数,分别用来处理返回的成功状态的promise对象和失败状态的对象,但then方法是异步执行的,因此,当运行到then方法时,可能fn还没有执行完毕,因此,需要在constructor中分别声明事件队列用来记录then方法中的两个函数,那么,相应的fn方法中resolve方法需要遍历执行成功事件队列,reject方法需要遍历执行失败事件队列。

    class Promise2 {

        constructor(fn) {
            const _this = this;

            _this.status = '';
            _this._queue = [];
            _this._succ_res = null;
            _this._erro_res = null;

            fn(function(...arg) {
                _this._succ_res = arg;
                _this.status = 'success';

                _this._queue.forEach(function(json) {
                    json.fn1(...arg);
                });
            }, function(...arg) {
                _this._erro_res = arg;
                _this.status = 'error';

                _this._queue.forEach(function(json) {
                    json.fn2(...arg);
                });
            });
        }

        then(fn1, fn2) {
            if (this.status === 'success') {
                fn1(this._succ_res);

            } else if (this.status === 'error') {
                fn2(this._erro_res);
            } else {
                this._queue.push({fn1, fn2});
            }
        }
    }



    Promise2.all = function(arr){
        let res = [];
        return new Promise2(function(resolve, reject){
            let i = 0;
            next();
            function next() {
                arr[i].then(function(result){
                    res.push(result);

                    i++;

                    if(i === arr.length){
                        resolve(res);
                    }else{
                        next();
                    }
                },reject);
            }

        })

    };

6.Promise应用

Promise适用于一次对很多数据情况。


let p1=new Promise(function (resolve, reject){
      $.ajax({
        url: 'data/arr.txt',
        dataType: 'json',
        success(arr){
          resolve(arr);
        },
        error(err){
          reject(err);
        }
      })
    });
    let p2=new Promise(function (resolve, reject){
      $.ajax({
        url: 'data/json.txt',
        dataType: 'json',
        success(arr){
          resolve(arr);
        },
        error(err){
          reject(err);
        }
      })
    });

    Promise.all([
      p1, p2
    ]).then(function (arr){
      let [res1, res2]=arr;

      alert('全都成功了');
      alert(res1);
      alert(res2);
    }, function (){
      alert('至少有一个失败了');
    });

6.Generator

1.基本概念

生成器对象是由一个 generator function 返回的,并且它符合可迭代协议和迭代器协议。普通函数是一路执行到底,Generator可以中间暂停。
语法如下:

function show(){
    alert("a")
    alert("b")
}
show(); //一次性执行完整个函数

function *show2(){
    alert("a")
    yield
    alert("b")
}
let geneObj = show2();
show2().next()   //alert a
show2().next()   //alert b 

可以理解为:Generator函数底层实现是把一个“大函数”生成多个yield分割的“小函数”。

2.yield

  • 可以传参数
let geneObj = show2();
geneObj.next();//第一个参数无效,可以在show()函数中设置参数,show(12);
geneObj.next(12);
  • 可以返回值

理解yield,可以通过下图来理解理解yield。

yield

3.Generator使用

1.在NodeJS中:

npm install yield-runner-blue  //安装blue封装的包

runner(function *(){
    let data1 = $.ajax(url, dataType:'json')
    let data2 = $.ajax(url, dataType:'json')
    let data3 = $.ajax(url, dataType:'json')
    console.log(data1, data2, data3)
})

2.异步操作

Generator generator 带逻辑的异步更方便,Promise适合一次读一堆,不适合带逻辑异步操作

  • Promise
Promise.all([
  $.ajax({url: xxx, dataType: 'json'})
  $.ajax({url: xxx, dataType: 'json'})
  $.ajax({url: xxx, dataType: 'json'})
]).then(result=>{

}, error=>{

})
  • Generator
runner(function *(){
  let data1 = yield $.ajax({url: xxx, dataType: 'json'})
  let data2 = yield $.ajax({url: xxx, dataType: 'json'})
  let data3 = yield $.ajax({url: xxx, dataType: 'json'})
});

//带逻辑的 generator
runner(function *(){
  let userData = yield $.ajax(url: 'getUserType', dataType: 'json')
  if (userData == 'VIP') {
      let VipUser = yield $.ajax(url: 'getVipUsers', dataType: 'json')
      } else {
          let normalUser = yield $.ajax(url: 'getNormalUsers', dataType: 'json')
      }

  //其他逻辑
})

猜你喜欢

转载自blog.csdn.net/wkl115211/article/details/82314338