ECMAScript 6 新特性

832 阅读7分钟

ECMAScript 6新语法

ECMAScript 6简介

ECMAScript 6(简称ES6)是JavaScript语言的下一代标准,已于2015年6月正式发布。

目标与愿景

  1. 适应更复杂的应用
  2. 实现代码库之间的共享
  3. 不断迭代维护新版本
  4. 支持更多语法,使用更方便

新的变量声明方式

let/const

  1. 与var不同,新的变量声明方式带来了一些不一样的特性,其中最重要的两个特性就是提供了块级作用域与不再具备变量提升。
  2. let:不可重复声明,块级作用域,值可更改。const:声明常量,块级作用域,值不可更改。
  3. 在ES6之前,使用var声明变量,可以声明多次变量,这样导致的问题查找很难。
  4. 在ES6中,使用let声明变量,使用const声明常量。

解构赋值

  1. 解构赋值语法是一种JavaScript表达式,用来将数组中的值或对象中的属性取出来区分为不同变量。
  2. 解构赋值分为对象解构赋值和数组解构赋值。
  3. 解构赋值能很好的运用在对象中,但它同样也能很好的作用于数组中。
  4. 解构赋值使用注意事项:两边的结构必须一致。右边必须是一个实际的内容,数组或对象。
  5. 例子:定义一个对象,表示三维空间中的一个点,需要用这些坐标点进行开平方计算。
<script>
    //第一种
    let newPoint={
        x:2,
        y:4,
        z:5
    }
    let x=newPoint.x;
    let y=newPoint.y;
    let z=newPoint.z;
    let distance=Math.sqrt(x*x+y*y+z*z);
    console.log(distance);
    //第二种
    let newPoint={
        x:2,
        y:4,
        z:5
    }
    let{x,y,z}=newPoint;
    let distance=Math.sqrt(x*x+y*y+z*z);
    console.log(distance);
    //第三种
    let newPoint=[2,4,5];
    let[x,y,z]=newPoint;
    let distance=Math.sqrt(x*x+y*y+z*z);
    console.log(distance);
</script>

箭头函数

  1. 箭头函数是ES6提供的语法结构,用于替换匿名函数。
  2. 箭头函数相当于简写了function,使用()代替,使用"=>"代替{}。
  3. 传递两个参数,参数必须使用括号包裹着。
  4. 如果使用return返回一个执行语句,可以省略return。
var add=(a,b)=>a+b;
console.log(add(1,2));

箭头函数与变通函数的区别

  1. 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
  2. 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
  3. 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。
  4. 不可以使用yield命令,因此箭头函数不能用作Generator函数。(generator函数现在经常用async替代)。

剩余参数

  1. "..."用于声明剩余的参数,也称为扩展运算符,通过"..."运算使得两个数组可以实现深拷贝。
//深拷贝
let arr1 = [1,2,3,4];
let arr2 = arr1;
console.log(arr2);
arr2.push(6);
console.log(arr1);

let arr3 = [...arr1];
console.log(arr3);
arr3.push(9);
console.log(arr1);
console.log(arr3);
  1. 传递三个参数,实现一个计算任意个数之和的add函数,传递参数的时候,可以使用"..."。
<script>
    //传递参数
    let arr=[1,2,3];
    console.log(arr);
    console.log(...arr);
    function add(a,b,c){
        console.log(a+b+c);
    }
    add(...arr);
    
    //连接两个数组
    let arr1=[1,2,4];
    let arr2=[3,5,6];
    let arr3=[...arr1,...arr2];
    console.log(arr3);
</script>
  1. 对象展开,可以在定义新的对象时,将原有对象补充进去,作用"..."。
<script>
    let obj={
        a:1,
        b:2,
        c:3
    }
    let obj1={
        ...obj,
        d:4
    }
    console.log(obj);
    console.log(obj1);
</script>

参数模板

  1. 模板字符串是为了解决使用"+"号拼接字符串的不使得而出现的
  2. 参数模板的功能非常强大,但是大多数时候使用它则非常简单。
  3. ${变量名称/常量名称},外面使用``(反引号)包裹。

数组方法

  1. Array.of(变量):将变量转为数组,可以不要再使用eval进行转换,替代Array()或new Array()。
  2. 实例方法fill(value,start,end):使用给定值填充数组,数组中的原有元素会被抹去,从位置start开始填充,不包含end位置。
  3. 遍历数组以下三个方法都返回一个遍历器对象,可以使用for...of循环遍历,或使用next()遍历。entries():键值对遍历。keys():键名遍历。values():键值遍历。
  4. 数组遍历方法:forEach、map、filter、find、every、some、reduce。
  5. map():返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。例:
<script>
        let scores = [23,45,76,85,12,91];
        let scores1 = scores.map(score =>{
            if(score >= 60){
                return '及格';
            }else{
                return '不及格';
            }
        });
        console.log(scores);
        console.log(scores1);
</script>
  1. reduce():接收函数作为累加器,数组的元素从左到右缩减,最计算一个值。例:
<script>
        let scores = [23,45,76,85,12,91];
        let average = scores.reduce((tmp,score,index)=>{
            console.log(tmp,score,index);
            if(index == score.length-1){
                return (tmp + score)/scores.length;
            }else{
                return tmp + score;
            }
        })
        console.log(average.toFixed(2));
</script>
  1. filter():创建新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

JavaScript异步编程

JavaScript的执行环境是"单线程",若有多个任务,就必须排队等待,解决这个问题的方案:异步编程。

方案

  1. 回调函数Callback
  2. 事件监听
  3. 发布订阅
  4. Promise/A+
  5. 生成器Generators/yield
  6. async/Awaite

Promise

  1. 异步编程的解决方案,比传统的解决方案更合理和更强大,完美解决回调地狱问题。
  2. Promise简单来说就是一个容器,保存某个未来才会结束的事件。

Promise对象的特点

  1. 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
  2. 一旦状态改变,就不会在变。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。
  3. Promise的原理:
  4. ES6规定,Promise对象是一个构造函数,用来生成Promise实例。
  5. Promise实例必须实现then()。
  6. then()必须可以接收两个函数作为参数。
  7. then()必须返回Promise实例。

前端模块化

JavaScript模块化进程

  1. 全局function模式:将不同功能封装成不同的全局函数,会污染全局命名空间。
  2. namespace模式:简单对象封装,解决了命名冲突,但是数据不安全。
  3. IIFE模式:匿名函数自调用(闭包),解决了数据安全,但模块依赖存在问题。
  4. IIFE模式增强:引入依赖,现代模块实现的基石。增强模块间的依赖关系。

模块化的优势

  1. 避免命名冲突(减少命名空间污染)
  2. 更好的分离,按需加载
  3. 更高复用性
  4. 高可维护性

引入多个"script"后出现的问题

问题

请求过多、依赖模糊、难以维护

解决方案

  1. 模块化规范:CommonJS、AMD、ES6、CMD等规范。
  2. CommonJS:Node应用采用CommonJS模块规范。主要用于服务器端。
  3. AMD:非同步加载模块,允许指定回调函数。浏览器端一般采用AMD规范。
  4. ES6:ES6模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
  5. CMD:专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。CMD规范整合了CommonJS和AMD规范的特点。

模块化方案的选择

CommonJS

  1. Node应用由模块组成,采用CommonJS模块规范。
  2. 每个文件就是一个模块,有自己的作用域。
  3. 在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
  4. 在服务器端,模块的运行时同步加载的。
  5. 在浏览器端,模块需要提前编译打包处理。

CommonJS特点

  1. 所有代码都运行在模块作用域,不会污染全局作用域。
  2. 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存,以后再加载就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
  3. 模块加载的顺序,按照其在代码中出现的顺序。

CommonJS基本语法

  1. 暴露模块:module.exorts=value;exports.xxx=value。
  2. 引入模块:require(xxx),如果是第三方模块,xxx为模块名。如果是自定义模块,xxx为模块文件路径。
  3. CommonJS规范规定:每个模块内部,module变量代表当前模块,它的exports属性(即module.exports)是对外的接口。
  4. 加载某个模块,就是加载该模块的module.exports属性。