1.变量声明:const和let
ES6推荐使用let声明局部变量,相比之前的var(无论声明在何处,都会被视为声明在函数的最顶部)
let和var声明的区别:
var x = '全局变量';
{
let x = '局部变量';
console.log(x); // 局部变量
}
console.log(x); // 全局变量
let表示声明变量,而const表示声明常量,两者都为块级作用域;const 声明的变量都会被认为是常量,意思就是它的值被设置完成后就不能再修改了:
const a = 1
a = 0 //报错
如果const的是一个对象,对象所包含的值是可以被修改的。抽象一点儿说,就是对象所指向的地址没有变就行:
const student = { name: 'cc' }
student.name = 'yy';// 不报错
student = { name: 'yy' };// 报错
注意点:
- let关键词声明的变量不具备变量提升特性
- let和const声明只在最靠近的一个块中(花括号内)有效
- 当使用常量const声明时,请使用大写变量
- const在声明时必须被赋值
var let const声明变量的区别:
- var声明的变量不支持块作用域,支持声明前置,可以重复定义,并且值可以改动。
- let声明的变量支持块作用域,不支持声明前置,不能重复定义,并且值可以修改。
- const定义常量,声明的常量支持块作用域,不支持声明前置,不能重复定义,并且无法修改,值通常是值的类型,不能用来定义循环变量
2.模板字符串
在ES6之前,我们往往这么处理模板字符串:
通过"/“和”+"来构建模板
$("body").html("This demonstrates the output of HTML \
content to the page, including student's\
" + name + ", " + seatNumber + ", " + sex + " and so on.");
ES6之后
- 基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定;
- ES6反引号(``)直接搞定;
$("body").html(`This demonstrates the output of HTML content to the page,
including student's ${name}, ${seatNumber}, ${sex} and so on.`);
3.箭头函数
在ES6中,箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个 =>,紧接着是函数体;
箭头函数最直观的三个特点:
- 不需要 function 关键字来创建函数
- 省略 return 关键字
- 继承当前上下文的 this 关键字
// ES5
var add = function (a, b) {
return a + b;
};
// 使用箭头函数
var add = (a, b) => a + b;
// ES5
[1,2,3].map((function(x){
return x + 1;
}).bind(this));
// 使用箭头函数
[1,2,3].map(x => x + 1);
注意点:
当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略{} 和 return;
4.函数参数默认值
定义默认参数语法(key = value)
5.对象和数组的解构
ES6支持解构语法,比如数组解构(var [a, b, c] = [0, 1, 2])
6.for…of和for…in(用来遍历实现迭代器接口的数据)
for…in 用来遍历对象中的属性:
let stus = ["Sam", "22", "男"];
for (let stu in stus) {
console.log(stus[stu]);
}
// 结果: Sam, 22, 男
缺点:
- 数组的键名是数字,但是for…in循环以字符串作为键名
- for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键
- 某些情况下,for…in循环会以任意顺序遍历键名
总之,for…in循环主要是为遍历对象而设计的,不适用于遍历数组
for…of 用于遍历一个迭代器,如数组:
let letters = ['a', 'b', 'c'];
letters.size = 3;
for (let letter of letters) {
console.log(letter);
}
// 结果: a, b, c
优点:
- 有着同for…in一样的简洁语法,但没有for…in的缺点
- 不同于forEach方法,他可以与breal,contiue和return配合使用
- 提供了遍历所有数据结构的统一操作接口
7.ES6中的类
ES6 中支持 class 语法,不过,ES6的class不是新的对象继承模型,它只是原型链的语法糖表现形式。
函数中使用Class关键字定义类,用static关键字定义构造函数的方法和属性
class Student {
constructor() {
console.log("I'm a student.");
}
study() {
console.log('study!');
}
static read() {
console.log("Reading Now.");
}
}
console.log(typeof Student); // function
let stu = new Student(); // "I'm a student."
stu.study(); // "study!"
stu.read(); // "Reading Now."
用extends实现继承
class Phone {
constructor() {
console.log("I'm a phone.");
}
}
class MI extends Phone {
constructor() {
super();
console.log("I'm a phone designed by xiaomi");
}
}
let mi8 = new MI();
注意点:
- extends 允许一个子类继承父类,需要注意的是,子类的constructor 函数中需要执行 super() 函数。
- 类的声明不会提升(hoisting),如果你要使用某个 Class,那你必须在使用之前定义它,否则会抛出一个 ReferenceError
的错误 - 在类中定义函数不需要使用 function 关键词
8.Promise
ES6原生提供了Promise对象,他是用来处理异步操作的,他代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的API,可供进一步操作
Promise有3种状态
- Pending是指初始状态,非Fulfilled或Rejected状态
- Resolved是指成功的操作
- Rejected是指失败的操作
Promise对象的两大特点
- 对象的状态不受外界影响,Promise对象代表一个异步操作,有三种状态,只有异步操作的结果,可以决定当前是哪个状态,任何其他操作都无法改变这个状态,这也是Promise这个名字的由来,英文翻译为承诺,允诺,表示其他手段无法改变
- 一旦状态改变,就不会再改变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能,从Pending改编为Resolved和从pending改编为rejected.只要这两种情况发生,状态就凝固了,会一直保持这个结果,不会再改变了,即使对Promise对象添加回调函数,也会立即得到这个结果,这与事件(Event)完全不同,事件的特点是,如果你错过了他,再去监听,也无法得到结果
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免层层嵌套的回调函数,此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise也有一些缺点,首先,无法取消promise,一旦新建,他就会立即执行,无法中途取消,其次,如果不设置回调函数,Promise内部抛出的错误不会反映到外部,最后处于pending状态,无法得知目前进展到哪一个阶段。
9.Symbol数据类型
symbol是ES6新增的数据类型,每个从Symbol()返回的symbol值都是唯一的。
10.async函数
async函数有以下几种形式
- 通过函数声明
async function foo(){}
- 通过表达式声明
var bar = async function(){}
3.通过对象声明
var obj = {
async bazfunction(){
}
}
4.通过箭头函数声明
var fot = async() => {}
async相对于Generator的优点
- generator函数需要调用next指令来运行异步的语句,async不需要调用next,想正常运行函数那样直接运行就行
- 相对于generator的*和yieId,async和await的语义化更明确
- await后面可以跟promise或者任何类型的值,yieId命令后面只能跟Thunk函数或者Promise对象
- async返回一个Promise对象,可以调用then和cache
11.super
super是一个关键字,用法为super(…)或者super.xxx(…)
因为super的语法定义和this不同,this的定义是this这个关键字会被替换成一个引用,而super这是super(…)会被替换成一个调用,除了可以在constructor里被直接调用super外,还可以使用super.xxx(…)
来调用父类上的某个原型方法,这同样是一个限定语法