ES6的特性

2020-08-17  本文已影响0人  累了就躺躺

ES6引入了class(类),让javaScript的面向对象课程变得更加简单和易于理解。

class Animal{
  constructor(name ,color){
    this.name = name;
    this.color = color;
  }
  
  toString(){
    console.log('name:'+this.name+',color:'+this.color);
  }
}

var animal = new Animal('dog','white');
animal.toString();

class Cat extends Animal{
  constructor(action){
    //子类必须要在constructor中指定super函数
    //如果没有置顶constructor,默认带super函数的constructor会被添加
    super('cat','white');
    this.action = action;
  }
  toString() {
    console.log(super.toString());
  }
}

var cat = new Cat('catch');

//实例cat 是 Cat和 Animal的实例和 Es5完全一致
console.log(cat instanceof Cat);
console.log(cat instanceof Animal);

模块化(Module)

ES5不支持原生的模块化,在ES6中模块作为重要的组成部分被添加进来。模块的功能主要由export和import组成。每一个模块都有自己单独的作用域,模块之间的相互调用关系是通过export来规定模块对外暴露的接口,通过import来引入其他模块提供的接口。同时还为模块创造了命名空间,防止函数的命名冲突。

导出(export)

ES6允许在一个模块中使用export来导出多个变量和函数。

导出变量

export var name = 'Rainbow';
//export 不仅支持变量的导出,也支持常量的导出
export const sqrt = Math.sqrt;

ES6将一个文件视为一个模块,上面的模块通过export向外输出了一个变量。一个模块也可以同时往外面输出多个变量。

var name = 'Radinbow';
var age = '24';
export{name,age};

导出函数

//myModule.js
export fuction myModule(someArg){
    return someArg;
}

导入(import)

定义好模块的输出以后就可以在另外一个模块通过import引用

import {myModule} from 'myModule'; //main.js
import {name,age} from 'test'
//一条import语句可以同时导入默认函数和其它变量
import defaultMethod,{otherMethod} from 'xxx.js';

箭头(Arrow)函数

这是ES6最令人激动的特性之一。=>不只是关键字function的简写,还带来了其它好处。箭头函数与包围它的代码共享一个this,能帮你很好的解决this的指向问题。有经验的javaScript开发者都熟悉如 var self = this;或var that = this这种引用外围this的模式。但借助=>,就不需要这种模式了。

箭头函数的结构

//箭头前空括号
()=> 1
//箭头前单个函数体
v=>v+1
//箭头前括号里面多个参数名,箭头后一个表达式作为函数返回值
(a,b)=>a+b
//花括号括起来的函数体,返回undefined
()=>{
    alert("foo");
}
//花括号括起来的函数体,自行return
e=>{
    if(e == 0){
        return 0;
    }
    return 1;
}

卸载监听器的陷阱

不论是函数还是bind,每次执行返回的都是一个新的函数引用,因为如果你需要用这个函数去做一些别的事情,比如卸载监听器,那么你需要保存这个引用。

错误做法

由于this.onAppPaused.bind(this)每次执行都会返回一个新的引用,导致无法移除监听器

class PauseMenu extends React.Component{
  componentWillMount() {
    AppStateIOS.addEventListener('change',this.onAppPaused.bind(this));
  }
  componentWillUnmount() {
    AppStateIOS.removeEventListener('change',this.onAppPaused.bind(this));
  }
  onAppPaused(event){
  }
}

正确的做法

class PauseMenu extends React.Component{

  constructor(props){
    super(props);
    this._onAppPaused = this.onAppPaused.bind(this);
  }

  componentWillMount() {
    AppStateIOS.addEventListener('change',this._onAppPaused);
  }
  componentWillUnmount() {
    AppStateIOS.removeEventListener('change',this._onAppPaused);
  }
  onAppPaused(event){
  }
}

除了以上做法,还可以

class PauseMenu extends React.Component{
  componentWillMount() {
    AppStateIOS.addEventListener('change',this.onAppPaused);
  }
  componentWillUnmount() {
    AppStateIOS.removeEventListener('change',this.onAppPaused);
  }
  //把函数直接作为一个arrow function的属性来定义,初始化的时候就绑定好了this指针。
  onAppPaused = (event) =>{
  }
}

函数参数的默认值

function foo(height = 50,color = 'red'){
}

//不使用默认值
function foo(height,color){
    var height = height || 50;
    var color = color || 'red';
}

这样写一般没有问题,但是当我们的参数为false的时候,就会出现一些问题。比如 foo(0,""),这样会导致height取值50,color取值red。

模板字符串

https://www.jianshu.com/p/287231fbbc71

解构赋值

解构赋值语法是JavaScript中的一种表达式,可以方便的从数组或者对象中快速提取赋值给定义的变量。

获取数组中的值

从数组中获取值并赋值到变量中,变量的顺序与数组中对象顺序对应。

var foo = ["one","two","three","four"];

var [one,two,three] = foo;

console.log(one); //"one"
console.log(two);  //"two"
console.log(three); //"three"

//如果你要忽略某些值
var [first,,last] = foo;
console.log(first); // "one"
console.log(last); // "four"

//也可以这么写
var a,b; //先申明变量

[a,b] = [1,2];
console.log(a); // 1
console.log(b); // 2

如果你没有从数组中的获取到值,你可以为变量设置一个默认值

var a,b;

[a=5,b=7] = [1];
console.log(a); // 1
console.log(b); // 7

通过结构赋值可以方便的交换两个变量的值

var a = 1;
var b = 3;

[a,b] = [b,a];
console.log(a); // 3
console.log(b); // 1

获取对象中的值

const student = {
  name:'Ming',
  age:'18',
  city:'Shanghai'
};

const {name,age,city} = student;
console.log(name); //"Ming"
console.log(age); // "18"
console.log(city); // "Shanghai"

延展操作符(Spread operator)

延展操作符 ... 可以在函数调用/数组构造时,将数组表达式或者string在语法层次展开;还可以在构造对象时,将对象表达式按key-value的方式展开

语法

函数调用

myFuction(...iterableObj)

数组构造或字符串

[...iterableObj,'4',...'hello',6];

构造对象时,进行克隆或者属性拷贝(ECMAScript 2018规范新增特性)

let objClone = {...obj};

应用场景

在函数调用时使用延展操作符

function sum(x,y,z) {
  return x + y + z;
}

const  numbers = [1,2,3];

//不使用延展操作符
console.log(sum.apply(null,numbers));

//使用延展操作符
console.log(sum(...numbers)); // 6

构造数组
没有展开语法的时候,只能组合使用push,splice,concat等方法,将已有数组元素变成新数组的一部分,有了展开语法,构造新数组会变得更简单、更优雅。

const students = ['Jine','Tom'];
const persons = ['Tony',...students,'Aaron','Anna'];
console.log(persons);// ['Tony','Jine','Tom','Aaron','Anna'];

和参数列表的展开类似,...在构造字数组时,可以在任意位置多次使用
数组拷贝

var arr = [1,2,3];
var arr2 = [...arr]; //等同于 arr.slice()
arr2.push(4);
console.log(arr2); //[1,2,3,4]

展开语法和Object.assign()行为一致,执行的都是浅拷贝(只遍历一层)
连接多个数组

var arr1 = [0,1,2];
var arr2 = [3,4,5];
var arr3 = [...arr1,...arr2];//将arr2中所有元素附加到arr1后面并返回
//等同于
var arr4 = arr1.concat(arr2);

在ECMA Script2018中延展操作符添加了对对象的支持

var obj1 = {foo:'bar',x:42};
var obj2 = {foo:'baz',y:13};

var clonedObj = {...obj1};
//克隆后的对象:{foo:'bar',x:42}

var  mergeObj = {...obj1,...obj2};
//合并后的对象 {foo:'baz',y:13}

React中的应用

通常我们封装一个组件时,会对外公开一些props用于实现功能。大部分情况下在外部使用都应显示的传递props。但是当传递大量的props时,会非常繁琐,我们这时候可以使用 ...(延展操作符,用于取出参数对象的所有可遍历属性)来进行传递。

一般情况下我们应该这样写

<CustomComponent name='Jine' age={21}/>

//使用...,等同于上面的写法
const params = {
  name : 'Jine',
  age : 21
}

<CustomComponent {...params}/>

//配合结构赋值避免传入一些不需要的参数
var params = {
  name : '123',
  title : '456',
  type : 'aaa'
}

var {type,...other} = params;

<CustomComponent type='normal' number={2} {...other}/>
//等同于
<CustomComponent type='normal' number={2} name='123' title='456'/>

对象属性简写

在ES6中允许我们在设置一个对象的属性的时候不指定属性名。

//不使用ES6
const name='Ming',age='18',city='Shanghai';

const student = {
  name:name,
  age:age,
  city:city
};
console.log(student) // {name:'Ming',age='18',city='Shanghai'}

//对象中必须包含属性和值,显得非常冗余,使用ES6
const name='Ming',age='18',city='Shanghai';

const student = {
  name,
  age,
  city
};
console.log(student) // {name:'Ming',age='18',city='Shanghai'}

Promise

Promise是异步编程的一种解决方法,比传统的解决方案callback更加的优雅。它最早由社区提出和实现的,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。

//不使用ES6 
//嵌套两个setTimeout回调函数
setTimeout(function(){
  console.log('Hello'); //1秒后输出"Hello"
  setTimeout(function(){
    console.log('Hi'); //2秒后输出"Hi"
  },2000)
},1000);

//使用ES6
var waitSecond = new Promise(function (resolve,reject) {
  setTimeout(resolve,1000);
})

waitSecond
    .then(function () {
        console.log("Hello"); // 1s后输出"Hello"
        return waitSecond;
    })
    .then(function () {
        console.log("Hi"); // 2s后输出"Hi"
    });

上面的代码使用两个then来进行异步编程串行化,避免了回调地狱。

ES7特性

Array.prototype.includes()

includes() 函数用来判断一个数组是否包含指定的值,包含返回true,反之false。
includes 函数与 indexOf 函数很相似,下面表达式等价

arr.includes(x)
arr.indexOf(x) >= 0

指数操作符

ES7中引入指数操作符 ** 等价于 Math.pow(..)

上一篇下一篇

猜你喜欢

热点阅读