title: es6 新特性
preview: imgs/preview/es6_1.jpg
preview_text: es6 新特性 主要包含“类、模块化、箭头函数、函数参数默认值、模板字符串、解构赋值、延展操作符、对象属性简写、Promise、let与const”
tags:
- javascript
---
1. 类(class)
这三个特性涉及了ES5中最令人头疼的的几个部分:原型、构造函数,继承...ES6提供了更接近传统语言的写法,引入了Class(类)这个概念。新的class写法让对象原型的写法更加清晰、更像面向对象编程的语法,也更加通俗易懂。
class Animal {
constructor(name, color) { // 构造函数
this.name = name;
this.color = color;
}
toString() { // toString方法
console.log(`name: ${this.name}, color: ${this.color}`);
}
getName() { // 取值
return this.name;
}
setName(value) { // 存值
this.name = value;
}
getColor() { // 取值
return this.color;
}
setColor(value) { // 存值
this.color = value;
}
}
let animal = new Animal("cat", "white");
animal.toString(); // name: cat, color: white
console.log(animal.hasOwnProperty('name')) // true
console.log(animal.hasOwnProperty('toString')) // false
console.log(animal.__proto__.hasOwnProperty('toString')) // true
2. super 和 extends
使用新的super和extends关键字扩展类
class Cat extends Animal {
constructor(action = "catch thing",name, color) {
super("cat", "black"); // super用作函数, 必须在this使用前调用
this.action = action; // Cat 类本身属性
}
toString() {
super.toString();// super用作对象
}
getAction() {
return this.action;
}
setAction(value) {
this.action = value;
}
}
let cat = new Cat("eat fish");
cat.toString(); // name: cat, color: white
console.log(cat instanceOf Cat) // true
console.log(cat instanceOf Animal) // true
使用ES5编写同样功能的类
function Animal(name, color) {
this.name = name || "cat";
this.color = color || "orange";
}
Animal.prototype.toString = function() {
console.log(`name: ${this.name}, color: ${this.color}`);
}
function Cat (action, name, color) {
Animal.call(this, name, color);
this.action = action || "catch thing";
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.toString = function() {
Tree.prototype.toString.call(this);
}
Cat.prototype.setAction = function(value) {
this.action = value;
}
3. 模块化(Module)
es5不支持原生的模块化,在es6模块作为重要的组成部分被添加进来。模块的共能主要由export和import组成。每一个模块都有自己的单独的作用域,模块之间的调用是通过export来规定模块对外暴露的接口,通过import来引用其他模块提供的接口。同时模块还创造了命名空间,防止函数的命名冲突。
导出(export)
ES6允许在一个模块中使用export来导出多个变量和函数。
导出变量
export let varible = "test variable exprot";
export default varible;
let name = "cat";
let color = "yellow";
export {name, color}
导出常量
export const NUMBER_LENGTH = 20
导出函数
export function myModuleFn(somParams) {
return somParams
}
导入(import)
定义好模块的输出,就可以在另一个模块通过import导入
import varible from "test.js"
import {myModuleFn} from "myModuleFn";
import {name, color} from "./path/to/test.js";
4. 箭头函数(Arrow Function)
=>
不只是function
的简写,它还带来了其他好处。箭头函数与包围它的代码共享同一个this,能够帮你解决this的指向问题。有经验的javaScript开发者都熟悉var self = this或var that = this
这种引用外围的this的模式。但=>
就不需要这种模式了。
不论是箭头函数还是bind,每次被执行都返回的是一个新的函数引用,因此如果你还需要函数的引用去做别的一些事(如卸载监听器),那么你必须保存这个引用。
箭头函数与普通函数的区别
- 箭头函数是匿名函数,不能作为构造函数,不能使用new
- 箭头函数不绑定arguments,取而代之用rest参数...解决
- 箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值
- 箭头函数通过 call() 或 apply() 方法调用一个函数时,只传入了一个参数,对 this 并没有影响。
- 箭头函数没有原型属性
- 箭头函数不能当做Generator函数,不能使用yield关键字
- 箭头函数的 this 永远指向其上下文的 this ,任何方法都改变不了其指向,如 call() , bind() , apply()
普通函数的this指向调用它的那个对象
5. 模板字符串
ES6支持模板字符串,使得字符串的拼接更加简洁、直观。
- 不使用模板字符串
var name = 'your name is ' + first + ' ' + last;
- 使用模板字符串
var name = `your name is ${first} ${last}`;
在ES6中通过${}
就可以完成字符串拼接,只需要将变量放在大括号中。
7. 解构赋值
解构赋值语法是Javascript的一种表达式,可以方便的从数组或对象中快速提取值赋给定义的变量。
获取数组的值
从数据中获取值并赋值到的变量中,变量的顺序与数组中对象顺序对应
var foo = [{"a": "one"}, "two", "three", "four"];
var [one, two, three] = foo;
console.log(one, two, three)
// 如果你要忽略某些值, 你可以按照下面的写法获取你想要的值
var [first, , , last] = foo;
console.log(first, last)
var [a, b] = [1, 2]
console.log(a, b)
如果没有从数组中获取到值,可以为变量设置一个默认值。
var a ,b;
[a= 3, b=7]=[1]
获取对象的值
const student = {
name: "Nyan",
age: 27,
city: "ShenZhen"
}
const {name, age, city} = student;
console.log(name, age, city)
8. 延展操作符(Spread operator)
延展操作符...
可以在函数调用/数组构造时,将数组表达式或者string在语法层面展开;还可以在构造对象时,将对象表达式按key-value方式展开。
语法
- 函数调用
myFunction(...iterableObj)
- 数组构造或字符串
[...iterableObj, '4', ...'hello', 6]
- 构造对象时,进行克隆或属性拷贝(ES2018)新增特性:
let objClone = {...obj};
应用场景
- 在函数调用时使用延展操作符
function (x, y, z) {
return x + y + z;
}
const numbers= [1, 2, 3];
console.log(sum.apply(null, numbers))
console.log(sum(...numbers))
- 构造数组
没有延展操作符的时候,只能通过使用push, splice, concat等方法,来将已有的数组元素变成新数组的一部分。有了延展操作符,构造数组更加简单,优雅。
const students = ["Jack", "Tom"];
const persons = ["Jony", ...students, "Kin", "Anny"]
console.log(persons)
和参数列表的展开类似,...
在构造数组时,可以任意位置多次使用。
- 数组拷贝
var arr = [1, 2, 4];
var arr2 = [...arr]
arr2.push(5)
console.log(arr2)
展开语法,与object.assign()行为一致,执行的是都是浅拷贝(只遍历一层)
- 连接多个数组
var arr3 = [...arr1, ...arr3]
// 等同与
var arr4 = arr1.concat(arr2)
在ES2018中延展操作符增加了对对象的支持
var obj1 = {foo: "baz", x: 12};
var obj2 = {foo: "bar", y: 34};
var cloneObj = {...obj1};
var mergeObj = {...obj, ...obj2};
console.log(obj1, obj2)
- 在React中使用
通常我们在封装一个组件时,会对外公开一些props用于实现功能。大部分情况下在外部使用都应显示传递的props.但是当传递大量的props时,会非常繁琐,这时我们可以使用...延展操作符,用于取出参数对象的所有可遍历属性
,来进行传递 - 一般情况下,我们这样传递
- 使用...,等同于上面的写法
const params = {
name: "name",
age: 27
}
- 配合解构赋值避免传入一些不需要的参数
const params = {
name: "name",
age: 27,
type: "type Name"
}
var {type, ...other} = params;
9. 对象属性的简写
在ES6中允许我们在设置一个对象的属性的时候不指定属性名
- 不使用es6
const name= "name", age = 27
const student = {name: name,age: age, getName: function(){}}
对象必须包含属性和值,显得非常冗余
- 使用Es6
const name= "name", age = 27
const student = {name,age, function getName(){}}
10. Promise
Promise是异步编程的一种解决方案,比传统的解决方案callback更加优雅。它最早由社区提出与实现,ES6将其写进了语言标准,统一了写法,原生提供了Promise对象。
- 不使用ES6
setTimeout(function(){
console.log("promise test")
setTimeout(function(){
console.log("promise test 1")
}, 1000)
}, 1000)
- 使用ES6
var waitSecond = new Promise(function(resolve, reject){
setTimeout(resolve, 1000)
});
waitSeccond
.then(function(){
console.log("promise test")
return waitSecond
}).then(function(){
console.log("promise test 1")
})