当前位置: 首页 > news >正文

10个最佳ES6特性 ES7与ES8的特性

10个最佳ES6特性原文链接:https://blog.fundebug.com/201...
与ES8特性原文链接:https://blog.fundebug.com/201...
译者按: 人生苦短,我用ES6。

原文: Top 10 ES6 Features Every Busy JavaScript Developer Must Know

译者: Fundebug

为了保证可读性,本文采用意译而非直译,并且对源代码进行了大量修改。另外,本文版权归原作者所有,翻译仅用于学习。

小编推荐:Fundebug专注于JavaScript、微信小程序、微信小游戏,Node.js和Java线上bug实时监控。真的是一个很好用的bug监控服务,众多大佬公司都在使用。

ES6,正式名称是ECMAScript2015,但是ES6这个名称更加简洁。ES6已经不再是JavaScript最新的标准,但是它已经广泛用于编程实践中。如果你还没用过ES6,现在还不算太晚…

下面是10个ES6最佳特性,排名不分先后:

函数参数默认值
模板字符串
多行字符串
解构赋值
对象属性简写
箭头函数
Promise
Let与Const

模块化

1. 函数参数默认值

不使用ES6
为函数的参数设置默认值:

function foo(height, color)
{
    var height = height || 50;
    var color = color || 'red';
    //...
}

这样写一般没问题,但是,当参数的布尔值为false时,是会出事情的!比如,我们这样调用foo函数:

foo(0, "", "")
因为0的布尔值为false,这样height的取值将是50。同理color的取值为‘red’。

使用ES6

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

2. 模板字符串

不使用ES6
使用+号将变量拼接为字符串:

var name = 'Your name is ' + first + ' ' + last + '.'
使用ES6
将变量放在大括号之中:

var name = Your name is ${first} ${last}.
ES6的写法更加简洁、直观。

3. 多行字符串

不使用ES6
使用“nt”将多行字符串拼接起来:

var roadPoem = 'Then took the other, as just as fair,\n\t'
    + 'And having perhaps the better claim\n\t'
    + 'Because it was grassy and wanted wear,\n\t'
    + 'Though as for that the passing there\n\t'
    + 'Had worn them really about the same,\n\t'

使用ES6
将多行字符串放在反引号之间就好了:

var roadPoem = `Then took the other, as just as fair,
    And having perhaps the better claim
    Because it was grassy and wanted wear,
    Though as for that the passing there
    Had worn them really about the same,`

4. 解构赋值

不使用ES6
当需要获取某个对象的属性值时,需要单独获取:

var data = $('body').data(); // data有house和mouse属性
var house = data.house;
var mouse = data.mouse;

使用ES6
一次性获取对象的子属性:

var { house, mouse} = $('body').data()

对于数组也是一样的:

var [col1, col2]  = $('.column');

5. 对象属性简写

不使用ES6
对象中必须包含属性和值,显得非常多余:

var bar = 'bar';
var foo = function ()
{
    // ...
}

var baz = {
  bar: bar,
  foo: foo
};

使用ES6
对象中直接写变量,非常简单:

var bar = 'bar';
var foo = function ()
{
    // ...
}

var baz = { bar, foo };

6. 箭头函数

不使用ES6
普通函数体内的this,指向调用时所在的对象。

function foo() 
{
    console.log(this.id);
}

var id = 1;

foo(); // 输出1

foo.call({ id: 2 }); // 输出2

使用ES6
箭头函数体内的this,就是定义时所在的对象,而不是调用时所在的对象。

var foo = () => {
  console.log(this.id);
}

var id = 1;

foo(); // 输出1

foo.call({ id: 2 }); // 输出1

7. Promise

不使用ES6
嵌套两个setTimeout回调函数:

setTimeout(function()
{
    console.log('Hello'); // 1秒后输出"Hello"
    setTimeout(function()
    {
        console.log('Fundebug'); // 2秒后输出"Fundebug"
    }, 1000);
}, 1000);

使用ES6
使用两个then是异步编程串行化,避免了回调地狱:

var wait1000 = new Promise(function(resolve, reject)
{
    setTimeout(resolve, 1000);
});

wait1000
    .then(function()
    {
        console.log("Hello"); // 1秒后输出"Hello"
        return wait1000;
    })
    .then(function()
    {
        console.log("Fundebug"); // 2秒后输出"Fundebug"
    });

8. Let与Const

使用Var
var定义的变量未函数级作用域:

{
  var a = 10;
}

console.log(a); // 输出10

使用let与const
let定义的变量为块级作用域,因此会报错:(如果你希望实时监控JavaScript应用的错误,欢迎免费使用Fundebug)

{
  let a = 10;
}

console.log(a); // 报错“ReferenceError: a is not defined”
const与let一样,也是块级作用域。

9. 类

不使用ES6
使用构造函数创建对象:

function Point(x, y)
{
    this.x = x;
    this.y = y;
    this.add = function()
    {
        return this.x + this.y;
    };
}

var p = new Point(1, 2);

console.log(p.add()); // 输出3

使用ES6
使用Class定义类,更加规范,且你能够继承:

class Point
{
    constructor(x, y)
    {
        this.x = x;
        this.y = y;
    }

    add()
    {
        return this.x + this.y;
    }
}

var p = new Point(1, 2);

console.log(p.add()); // 输出3

10. 模块化

JavaScript一直没有官方的模块化解决方案,开发者在实践中主要采用CommonJS和AMD规范。而ES6制定了模块(Module)功能。

不使用ES6
Node.js采用CommenJS规范实现了模块化,而前端也可以采用,只是在部署时需要使用Browserify等工具打包。这里不妨介绍一下CommenJS规范。

module.js中使用module.exports导出port变量和getAccounts函数:

module.exports = {
  port: 3000,
  getAccounts: function() {
    ...
  }
}

main.js中使用require导入module.js:

var service = require('module.js')
console.log(service.port) // 输出3000

使用ES6
ES6中使用export与import关键词实现模块化。

module.js中使用export导出port变量和getAccounts函数:

export var port = 3000
export function getAccounts(url) {
  ...
}

main.js中使用import导入module.js,可以指定需要导入的变量:

import {port, getAccounts} from 'module'
console.log(port) // 输出3000

也可以将全部变量导入:

import * as service from 'module'
console.log(service.port) // 3000

Es7与Es8的特性

ES7只有2个特性:
includes()
指数操作符

ES8的一些特性:

Object.values()
Object.entries()
padStart()
padEnd()
Object.getOwnPropertyDescriptors()
函数参数列表结尾允许逗号
Async/Await
Array.prototype.includes()
不使用ES7
使用indexOf()验证数组中是否存在某个元素,这时需要根据返回值是否为-1来判断:

let arr = ['react', 'angular', 'vue'];

if (arr.indexOf('react') !== -1)
{
    console.log('React存在');
}

使用ES7
使用includes()验证数组中是否存在某个元素,这样更加直观简单:

let arr = ['react', 'angular', 'vue'];

if (arr.includes('react'))
{
    console.log('React存在');
}

指数操作符
不使用ES7
使用自定义的递归函数calculateExponent或者Math.pow()进行指数运算:

function calculateExponent(base, exponent)
{
    if (exponent === 1)
    {
        return base;
    }
    else
    {
        return base * calculateExponent(base, exponent - 1);
    }
}

console.log(calculateExponent(7, 3)); // 输出343
console.log(Math.pow(7, 3)); // 输出343

使用ES7
使用指数运算符**,就像+、-等操作符一样:

console.log(7**3);
Object.values()

不使用ES8
使用Object.keys()遍历对象的属性值,需要通过属性名key去获取属性值:

let obj = {a: 1, b: 2, c: 3};

Object.keys(obj).forEach((key) =>
{
    console.log(obj[key]); // 输出1, 2, 3
});

使用ES8
使用Object.values()遍历对象的属性值,无需使用使用属性名:

let obj = {a: 1, b: 2, c: 3}
Object.values(obj).forEach(value =>
{
    console.log(value); // 输出1, 2, 3
});
Object.entries()

不使用ES8
使用Object.keys()遍历对象的属性名和属性值:

let obj = {a: 1, b: 2, c: 3};

Object.keys(obj).forEach((key) =>
{
    console.log(key + ": " + obj[key]); // 输出a: 1, b: 2, c: 3
})

使用ES8
使用Object.entries()遍历对象的属性名和属性值:

let obj = {a: 1, b: 2, c: 3};

Object.entries(obj).forEach(([key, value]) =>
{
    console.log(key + ": " + value); // 输出a: 1, b: 2, c: 3
})
padStart()

不使用ES8

console.log('0.00')             
console.log('10,000.00')    
console.log('250,000.00')
输出结果如下:

0.00
10,000.00
250,000.00

使用ES8
使用padStart()可以在字符串前面填充指定的字符串:

console.log('0.00'.padStart(20))             
console.log('10,000.00'.padStart(20))    
console.log('250,000.00'.padStart(20))
输出结果如下:

      0.00
 10,000.00
250,000.00
padEnd()

不使用ES8

console.log('0.00 ' + '0.00' )             
console.log('10,000.00 ' + '10,000.00' )    
console.log('250,000.00 ' + '250,000.00')
输出如下:

0.00 0.00
10,000.00 10,000.00
250,000.00 250,000.00

使用ES8
使用padEnd()可以在字符串后面填充指定的字符串:

console.log('0.00'.padEnd(20) + '0.00' )             
console.log('10,000.00'.padEnd(20) + '10,000.00' )    
console.log('250,000.00'.padEnd(20) + '250,000.00')
输出如下:

0.00                0.00
10,000.00           10,000.00
250,000.00          250,000.00

Object.getOwnPropertyDescriptors()

azatsBooks对象的定义如下:

let azatsBooks = {
    books: ['React Quickly'],
    get latest()
    {
        let numberOfBooks = this.books.length;
        if (numberOfBooks == 0) return undefined;
        return this.books[numberOfBooks - 1];
    }
};

不使用ES8
使用Object.getOwnPropertyDescriptor()获取单个属性的属性描述符。

获取azatsBooks对象的books属性的属性描述符:

console.log(Object.getOwnPropertyDescriptor(azatsBooks, 'books'));

/** 输出books属性的属性描述
[object Object] {
  configurable: true,
  enumerable: true,
  value: ["React Quickly"],
  writable: true
}
**/
获取azatsBooks对象的lastest方法的属性描述符:

console.log(Object.getOwnPropertyDescriptor(azatsBooks, 'latest'));

/** 输出lastest方法的属性描述
[object Object] {
  configurable: true,
  enumerable: true,
  get: function get latest() {
    let numberOfBooks = this.books.length
    if (numberOfBooks == 0) return undefined
    return this.books[numberOfBooks - 1]
  },
  set: undefined
}
**/

使用ES8
Object.getOwnPropertyDescriptors()相当于Object.getOwnPropertyDescriptor()的复数形式,可以获取对象的所有自身属性的描述符:

console.log(Object.getOwnPropertyDescriptors(azatsBooks))

/** 输出azatsBooks对象所有自身属性的属性描述
[object Object] {
  books: [object Object] {
    configurable: true,
    enumerable: true,
    value: ["React Quickly"],
    writable: true
  },
  latest: [object Object] {
    configurable: true,
    enumerable: true,
    get: function get latest() {
      let numberOfBooks = this.books.length
      if (numberOfBooks == 0) return undefined
      return this.books[numberOfBooks - 1]
    },
    set: undefined
  }
}
**/

函数参数列表结尾允许逗号
不使用ES8

var f = function(a,
  b,
  c,
  d // d之后不能带逗号
   ) { 
  console.log(d)
}

使用ES8

var f = function(a,
  b,
  c,
  d, // d之后允许带逗号
) { 
  console.log(d)
}

允许逗号之后,可以避免一些不必要的报错。(如果你希望实时监控JavaScript应用的错误,欢迎免费使用Fundebug)

Async/Await
使用Promise
使用Promise写异步代码,会比较麻烦:

axios.get(`/q?query=${query}`)
    .then(response => response.data)
    .then(data =>
    {
        this.props.processfetchedData(data);
    })
    .catch(error => console.log(error));

使用Async/Await
Async/Await使得异步代码看起来像同步代码,这正是它的魔力所在:

async fetchData(query) =>
{
    try
    {
        const response = await axios.get(`/q?query=${query}`);
        const data = response.data;
        return data;
    }
    catch (error)
    {
        console.log(error)
    }
}

fetchData(query).then(data =>
{
    this.props.processfetchedData(data)
})

Async/Await是写异步代码的新方式,以前的方法有回调函数和Promise。相比于Promise,它更加简洁,并且处理错误、条件语句、中间值都更加方便,因此有望替代Promise,成为新一代的一步代码编写方式。对细节感兴趣的话,可以查看Fundebug翻译的《Async/Await替代Promise的6个理由》。

相关文章:

  • 你以为AI只能帮景区刷脸买票?其实它的用处还有很多
  • 230. Kth Smallest Element in a BST
  • vss使用笔记
  • 使用 Docker 部署 Spring Boot项目
  • luogu P1706全排列问题
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • git
  • Mysql数据库的条件查询语句
  • 观《时间的朋友2017》总结
  • Angry Birds和广告系统泄露个人信息——FireEye对Angry Birds的分析
  • Vagrant (二) - 日常操作
  • 2017年终总结、随想
  • js
  • PHP multipart/form-data 远程DOS漏洞
  • java 内存分析 jmap
  • 分享的文章《人生如棋》
  • ESLint简单操作
  • IOS评论框不贴底(ios12新bug)
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • javascript数组去重/查找/插入/删除
  • jquery ajax学习笔记
  • npx命令介绍
  • React Transition Group -- Transition 组件
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • vue-router 实现分析
  • Webpack 4 学习01(基础配置)
  • 从零搭建Koa2 Server
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 类orAPI - 收藏集 - 掘金
  • 前端技术周刊 2019-01-14:客户端存储
  • 微信开源mars源码分析1—上层samples分析
  • 原生Ajax
  • MyCAT水平分库
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • #传输# #传输数据判断#
  • (八十八)VFL语言初步 - 实现布局
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (三)Honghu Cloud云架构一定时调度平台
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (五)MySQL的备份及恢复
  • (一)Neo4j下载安装以及初次使用
  • (原創) 物件導向與老子思想 (OO)
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)四层和七层负载均衡的区别
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .net 微服务 服务保护 自动重试 Polly
  • .NET开发不可不知、不可不用的辅助类(一)
  • .NET性能优化(文摘)
  • @javax.ws.rs Webservice注解
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • [ajaxupload] - 上传文件同时附件参数值
  • [Android]一个简单使用Handler做Timer的例子
  • [Apio2012]dispatching 左偏树