博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈ES6 常用 新特性 并了解其兼容性解决方案
阅读量:5818 次
发布时间:2019-06-18

本文共 7227 字,大约阅读时间需要 24 分钟。

es6 兼容性 如何使用babel来编译我们的js(es6)代码

首先来谈一下es6 es6在大多数情况是没问题,据了解国内的环境,大部分业务(银行系统除外)支持到IE8就可以了,如果要兼容到IE6+,可以借助babel插件来完成,只要babel支持的都没问题的。

ES6新特性在Babel下的兼容性列表

ES6特性 兼容性
箭头函数 支持
类的声明和继承 部分支持,IE8不支持
增强的对象字面量 支持
字符串模板 支持
解构 支持,但注意使用方式
参数默认值,不定参数,拓展参数 支持
let与const 支持
for of IE不支持
iterator, generator 不支持
模块 module、Proxies、Symbol 不支持
Map,Set 和 WeakMap,WeakSet 不支持
Promises、Math,Number,String,Object 的新API 不支持
export & import 支持
生成器函数 不支持
数组拷贝 支持

那么我们来说一下如何使用这个babel来兼容我们的es6 代码(当然前提是babeljs文件已经存在在项目中,这里只是说明如何在webpack中让babel编译我们的js或者是jsx文件)

上一小小段代码:

module: {        loaders: [            //            {                test: /\.(jsx|js)$/,                loader: ['babel-loader'],                exclude: /node_modules/            }        ]    }复制代码

一般处理我们的打包文件,我们都会放在module下的loader里去处理,上段代码中将以jsx/js为结尾的文件都会做一个babel来编译。

es6好用的新特性

1.var let const

在之前的js的版本中,我们多会选择用var来声明定义一个变量,这么做的弊端会造成浪费和占用了大量内存,在新的js版本es6中出现了两个新的用来声明标识符的方式:let 和 const

其实很好理解let其实定义了一个拥有着自己代码块的变量,所谓代码块其实就是当你在一个{}中使用let 定义一个变量后,let只在{}中存在,但是与js的函数作用域不同的是let定义的变量不会被提升。

var a = 1;function fn1(){    console.log(a);    a = 2;}console.log(a);//1fn1();  // 2var b = 2;function fn2(){    console.log(b);    let b = 1;}console.log(b)//2fn2();  //复制代码

从这个例子中我们可以看到分别打印a,b变量 用let改的值在出了函数{}后失去了作用,而不是用let的赋值在出了{}后依然生效。

再举一个好用的应用场景,我们在一些特定需求时,会避免不了使用闭包,不了解闭包请移步跨域 闭包 ,例如一个常见的烂大街的问题,一个ul里的li打印它的索引或者内容。在es5中我们是这样做的:

var arr = [];for(var i=0; i<5; i++){    arr.push((function (a){        return function (){            console.log(a);        }    })(i))}arr[1]()  // 1arr[2]()  // 2arr[3]()  // 3复制代码

闭包的缺点时会占用内存不是放掉,那么我们来换一种写法:

var arr = [];  // let arr = [] 都可以for(let i=0; i<5; i++){    arr.push(function (){        console.log(i)    })}arr[0]()  // 0arr[1]()  // 1arr[2]()  // 2复制代码

使用let会完美的解决这个问题。

再说说const就很好理解了,它就是定义一个常量的声明方式,拥有其他语言基础这个概念就不难理解,再次就不在做多余赘述。

2.解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

let [a, b, c] = [1, 2, 3];//等同于let a = 1;let b = 2;let c = 3;复制代码

对象的解构赋值:获取对象的多个属性并且使用一条语句将它们赋给多个变量。

var {  StyleSheet,  Text,  View} = React;等同于var StyleSheet = React.StyleSheet;var Text = React.Text;var View = React.View;复制代码

3.箭头函数

ES6中新增箭头操作符用于简化函数的写法,操作符左边为参数,右边为具体操作和返回值。

var sum = (num1, num2) => { return num1 + num2; }//等同于var sum = function(num1, num2) {    return num1 + num2; };复制代码

同时箭头函数还有修复了this的指向,使其永远指向词法作用域:

var obj = {    birth: 1990,    getAge: function () {        var b = this.birth; // 1990        var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象        return fn();    }};obj.getAge(); // 25复制代码

4.类 class

ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类,与多数传统语言类似。

//定义类

class Point {  constructor(x, y) {    this.x = x;    this.y = y;  }  toString() {    return '(' + this.x + ', ' + this.y + ')';  }}复制代码

同样的继承使用的是extends关键字

5.字符串

新增字符串处理函数:

startsWith() //检查是否以指定字符串开头,返回布尔值let str = 'javascript';str.startsWith('java'); endsWith() //检查是否以指定字符串结尾,返回布尔值let str = 'javascript'str.endsWith('pt');includes() //检查字符串是否包含指定字符串 ,返回布尔值let str = 'javascript';str.includes('j');repeat() //指定字符串重复次数let str = 'javascript';str.repeat('3');复制代码

Template Literals 字符串模板

使用 字符串模板字面量,我可以在字符串中直接使用特殊字符,而不用转义。

var text = "This string contains \"double quotes\" which are escaped.";let text = `This string contains "double quotes" which don't need to be escaped anymore.`;复制代码

字符串模板字面量 还支持直接插入变量,可以实现字符串与变量的直接连接输出.

var name = 'Tiger';var age = 13;console.log('My cat is named ' + name + ' and is ' + age + ' years old.');更简单的版本:const name = 'Tiger';const age = 13;console.log(`My cat is named ${name} and is ${age} years old.`);复制代码

ES5中,我们要这样生成多行文本:

var text = (    'cat\n' +    'dog\n' +    'nickelodeon');或者:var text = [    'cat',    'dog',    'nickelodeon'].join('\n');复制代码

字符串模板字面量 让我们不必特别关注多行字符串中的换行转义符号,直接换行即可:

let text = ( `catdognickelodeon`);复制代码

字符串模板字面量 内部可以使用表达式,像这样:

let today = new Date();let text = `The time and date is ${today.toLocaleString()};复制代码

6.第七种基本类型 Symbol

Symbols和其它基本类型大不一样。

从创建开始就是不可变的。你不能为它设置属性(如果你在严谨模式下尝试,会报类型错误)。它可以作为属性名。这是它的类字符串性质。
另一方面,每一个symbol都是唯一的。与其他的不同(就算他们的描述是一样的)你可以很容易地新创建一个。这是它的类对象性质。
ES6 symbols与Lisp和Ruby中的更传统的symbols很类似,但是没有如此紧密地集成到语言中。在Lisp中,所有的标识符都是symbols。在JS中,标识符和大多数属性的键值的首先仍是字符串,Symbols只是为开发人员提供了一个额外选择。
关于symbols的一个忠告:与JS中的其它类型不同,它不能被自动转换为字符串。试图拼接symbol与字符串将会引起类型错误。

(表示读过文档后依然蒙圈 先选择性放弃这个点)

7.Promise

一个 Promise 对象可以理解为一次将要执行的操作(常常被用于异步操作),使用了 Promise 对象之后可以用一种链式调用的方式来组织代码,让代码更加直观。而且由于 Promise.all 这样的方法存在,可以让同时执行多个操作变得简单。接下来就来简单介绍 Promise 对象。

直观些直接上代码:

function helloWorld (ready) {    return new Promise(function (resolve, reject) {        if (ready) {            resolve("Hello World!");        } else {            reject("Good bye!");        }    });}helloWorld(true).then(function (message) {    alert(message);}, function (error) {    alert(error);});复制代码

上面的代码实现的功能非常简单,helloWord 函数接受一个参数,如果为 true 就打印 "Hello World!",如果为 false 就打印错误的信息。helloWord 函数返回的是一个 Promise 对象。

在 Promise 对象当中有两个重要方法————resolve 和 reject。
resolve 方法可以使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作,在这个例子当中就是 Hello World!字符串。
reject 方法则是将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作。

Promise 的三种状态

上面提到了 resolve 和 reject 可以改变 Promise 对象的状态,那么它究竟有哪些状态呢?
Promise 对象有三种状态:

  • Fulfilled 可以理解为成功的状态
  • Rejected 可以理解为失败的状态
  • Pending 既不是 Fulfilld 也不是 Rejected 的状态,可以理解为 Promise 对象实例创建时候的初始状态
    helloWorld 的例子中的 then 方法就是根据 Promise 对象的状态来确定执行的操作,resolve 时执行第一个函数(onFulfilled),reject 时执行第二个函数(onRejected)。
    then 和 catch
    then
    helloWorld 的例子当中利用了 then(onFulfilld, onRejected) 方法来执行一个任务打印 "Hello World!",在多个任务的情况下 then 方法同样可以用一个清晰的方式完成。
    function printHello (ready) {return new Promise(function (resolve, reject) {    if (ready) {        resolve("Hello");    } else {        reject("Good bye!");   }});}复制代码

上述例子通过链式调用的方式,按顺序打印出了相应的内容。then 可以使用链式调用的写法原因在于,每一次执行该方法时总是会返回一个 Promise 对象。另外,在 then onFulfilled 的函数当中的返回值,可以作为后续操作的参数,因此上面的例子也可以写成:

printHello(true).then(function (message) {    return message;}).then(function (message) {    return message  + ' World';}).then(function (message) {    return message + '!';}).then(function (message) {    alert(message);});function printWorld () {    alert("World");}function printExclamation () {    alert("!");}printHello(true)    .then(function(message){    alert(message);    })    .then(printWorld)    .then(printExclamation);复制代码

同样可以打印出正确的内容。

catch
catch 方法是 then(onFulfilled, onRejected) 方法当中 onRejected 函数的一个简单的写法,也就是说可以写成 then(fn).catch(fn),相当于 then(fn).then(null, fn)。使用 catch 的写法比一般的写法更加清晰明确。
Promise.all 和 Promise.race
Promise.all 可以接收一个元素为 Promise 对象的数组作为参数,当这个数组里面所有的 Promise 对象都变为 resolve 时,该方法才会返回。

var p1 = new Promise(function (resolve) {    setTimeout(function () {        resolve("Hello");    }, 3000);});var p2 = new Promise(function (resolve) {    setTimeout(function () {        resolve("World");    }, 1000);});Promise.all([p1, p2]).then(function (result) {    console.log(result); // ["Hello", "World"]});复制代码

上面的例子模拟了传输两个数据需要不同的时长,虽然 p2 的速度比 p1 要快,但是 Promise.all 方法会按照数组里面的顺序将结果返回。

日常开发中经常会遇到这样的需求,在不同的接口请求数据然后拼合成自己所需的数据,通常这些接口之间没有关联(例如不需要前一个接口的数据作为后一个接口的参数),这个时候 Promise.all 方法就可以派上用场了。
还有一个和 Promise.all 相类似的方法 Promise.race,它同样接收一个数组,不同的是只要该数组中的 Promise 对象的状态发生变化(无论是 resolve 还是 reject)该方法都会返回。
兼容性
最后是关于 Promise 对象的兼容性问题。

在浏览器端,一些主流的浏览器都已经可以使用 Promise 对象进行开发,在 Node.js 配合 babel 也可以很方便地使用。

如果要兼容旧的浏览器,建议可以寻找一些第三方的解决方案,例如 jQuery 的 $.Deferred。

转载地址:http://hwzdx.baihongyu.com/

你可能感兴趣的文章
System and device programming——Virtual Memory
查看>>
脚本一键安装redis实现主从复制
查看>>
spring boot admin slack报警
查看>>
spring-data-jpa软删除方案
查看>>
聊聊reactor异步线程的变量传递
查看>>
PPP PAP 认证
查看>>
7.1 安装软件包的三种方法 7.2 rpm包介绍 7.3 rpm工具用法 7.4 yum工具用法
查看>>
第二本书unit 7 网络共享文件访问
查看>>
Linux精华篇—CentOS 7.4下源码编译构建LNMP架构
查看>>
理解Linux文件系统之inode
查看>>
有关字符串的整理
查看>>
Linux学习总结(五十五)keepalived+lvs 双机热备负载均衡架构
查看>>
WCF的WindowsService开发参考【附源码】
查看>>
高可用pcs
查看>>
C语言小题2
查看>>
配置华为防火墙ssh ASDM
查看>>
c3p0配置文件
查看>>
浅谈Java设计模式之工厂模式
查看>>
自动化运维工具 Ansible 的详细部署
查看>>
[笔记]在IDEA中使用Tomcat远程调试WEB项目时的相关配置
查看>>