ECMAScript 6新语法
ECMAScript 6简介
ECMAScript 6(简称ES6)是JavaScript语言的下一代标准,已于2015年6月正式发布。
目标与愿景
- 适应更复杂的应用
- 实现代码库之间的共享
- 不断迭代维护新版本
- 支持更多语法,使用更方便
新的变量声明方式
let/const
- 与var不同,新的变量声明方式带来了一些不一样的特性,其中最重要的两个特性就是提供了块级作用域与不再具备变量提升。
- let:不可重复声明,块级作用域,值可更改。const:声明常量,块级作用域,值不可更改。
- 在ES6之前,使用var声明变量,可以声明多次变量,这样导致的问题查找很难。
- 在ES6中,使用let声明变量,使用const声明常量。
解构赋值
- 解构赋值语法是一种JavaScript表达式,用来将数组中的值或对象中的属性取出来区分为不同变量。
- 解构赋值分为对象解构赋值和数组解构赋值。
- 解构赋值能很好的运用在对象中,但它同样也能很好的作用于数组中。
- 解构赋值使用注意事项:两边的结构必须一致。右边必须是一个实际的内容,数组或对象。
- 例子:定义一个对象,表示三维空间中的一个点,需要用这些坐标点进行开平方计算。
<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>
箭头函数
- 箭头函数是ES6提供的语法结构,用于替换匿名函数。
- 箭头函数相当于简写了function,使用()代替,使用"=>"代替{}。
- 传递两个参数,参数必须使用括号包裹着。
- 如果使用return返回一个执行语句,可以省略return。
var add=(a,b)=>a+b;
console.log(add(1,2));
箭头函数与变通函数的区别
- 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
- 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
- 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。
- 不可以使用yield命令,因此箭头函数不能用作Generator函数。(generator函数现在经常用async替代)。
剩余参数
- "..."用于声明剩余的参数,也称为扩展运算符,通过"..."运算使得两个数组可以实现深拷贝。
//深拷贝
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);
- 传递三个参数,实现一个计算任意个数之和的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>
- 对象展开,可以在定义新的对象时,将原有对象补充进去,作用"..."。
<script>
let obj={
a:1,
b:2,
c:3
}
let obj1={
...obj,
d:4
}
console.log(obj);
console.log(obj1);
</script>
参数模板
- 模板字符串是为了解决使用"+"号拼接字符串的不使得而出现的
- 参数模板的功能非常强大,但是大多数时候使用它则非常简单。
- ${变量名称/常量名称},外面使用``(反引号)包裹。
数组方法
- Array.of(变量):将变量转为数组,可以不要再使用eval进行转换,替代Array()或new Array()。
- 实例方法fill(value,start,end):使用给定值填充数组,数组中的原有元素会被抹去,从位置start开始填充,不包含end位置。
- 遍历数组以下三个方法都返回一个遍历器对象,可以使用for...of循环遍历,或使用next()遍历。entries():键值对遍历。keys():键名遍历。values():键值遍历。
- 数组遍历方法:forEach、map、filter、find、every、some、reduce。
- 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>
- 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>
- filter():创建新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
JavaScript异步编程
JavaScript的执行环境是"单线程",若有多个任务,就必须排队等待,解决这个问题的方案:异步编程。
方案
- 回调函数Callback
- 事件监听
- 发布订阅
- Promise/A+
- 生成器Generators/yield
- async/Awaite
Promise
- 异步编程的解决方案,比传统的解决方案更合理和更强大,完美解决回调地狱问题。
- Promise简单来说就是一个容器,保存某个未来才会结束的事件。
Promise对象的特点
- 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
- 一旦状态改变,就不会在变。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。
- Promise的原理:

- ES6规定,Promise对象是一个构造函数,用来生成Promise实例。
- Promise实例必须实现then()。
- then()必须可以接收两个函数作为参数。
- then()必须返回Promise实例。
前端模块化
JavaScript模块化进程
- 全局function模式:将不同功能封装成不同的全局函数,会污染全局命名空间。
- namespace模式:简单对象封装,解决了命名冲突,但是数据不安全。
- IIFE模式:匿名函数自调用(闭包),解决了数据安全,但模块依赖存在问题。
- IIFE模式增强:引入依赖,现代模块实现的基石。增强模块间的依赖关系。
模块化的优势
- 避免命名冲突(减少命名空间污染)
- 更好的分离,按需加载
- 更高复用性
- 高可维护性
引入多个"script"后出现的问题
问题
请求过多、依赖模糊、难以维护
解决方案
- 模块化规范:CommonJS、AMD、ES6、CMD等规范。
- CommonJS:Node应用采用CommonJS模块规范。主要用于服务器端。
- AMD:非同步加载模块,允许指定回调函数。浏览器端一般采用AMD规范。
- ES6:ES6模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
- CMD:专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。CMD规范整合了CommonJS和AMD规范的特点。
模块化方案的选择

CommonJS
- Node应用由模块组成,采用CommonJS模块规范。
- 每个文件就是一个模块,有自己的作用域。
- 在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
- 在服务器端,模块的运行时同步加载的。
- 在浏览器端,模块需要提前编译打包处理。
CommonJS特点
- 所有代码都运行在模块作用域,不会污染全局作用域。
- 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存,以后再加载就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
- 模块加载的顺序,按照其在代码中出现的顺序。
CommonJS基本语法
- 暴露模块:module.exorts=value;exports.xxx=value。
- 引入模块:require(xxx),如果是第三方模块,xxx为模块名。如果是自定义模块,xxx为模块文件路径。
- CommonJS规范规定:每个模块内部,module变量代表当前模块,它的exports属性(即module.exports)是对外的接口。
- 加载某个模块,就是加载该模块的module.exports属性。