现代 JavaScript,你应该使用的 10 件事,从今天开始

在Twitter 上关注我,很高兴收到您对主题或改进的建议/Chris

您可能对 JavaScript 完全陌生,或者多年来您可能只是偶尔使用它。不过有一件事很清楚 - 很多东西都发生了变化,并且您应该使用一些功能。这篇文章描述了我认为你应该每天使用的特性,如果你对 JavaScript 很认真的话

 

资源

这些是我最喜欢的 ES6+ 资源:

-1- 扩展运算符

这被表示为...一个对象或数组的前面,并完成了名字所说的,它将某些东西从一个结构变成了一个逗号分隔的列表。让我们演示一下:

展开数组

let firstHalf = [ 'one', 'two'];
let secondHalf = ['three', 'four', ...firstHalf];

这是一种很好且紧凑的编写方式。不这样做就意味着做这样的事情:

没有阵列传播

let firstHalf = [ 'one', 'two'];


let secondHalf = ['three', 'four'];
for(var i=0, i <firstHalf.length; i++ ) {
  secondHalf.push(firstHalf[i]);
}


这也可以用于对象作为合并其属性的一种方式:

传播对象

const hero = {
  name: 'Xena - Warrior Princess',
  realName: 'Lucy Lawless'
}


const heroWithSword = {
 ...hero,
 weapon: 'sword'
}

这样做很困难,我们将遍历对象上的所有属性:

NO 物体扩散

let keys = Object.keys(hero);
let obj = {};

for(var i=0; i< keys.length; i++) {
   obj[keys[i]] = keys[props[i]];
}

公平地说,还有Object.assign(),看起来像这样:

const heroWithSword = Object.assign({}, hero, {weapon:"sword"})

我仍然认为这是一个更容易阅读的内容:

const heroWithSword = {
 ...hero,
 weapon: 'sword'
}

-2-Rest parameter

剩余参数是关于将剩余参数收集到一个数组中。JavaScript 能够灵活地设置你给它的输入参数的数量。通常有一个arguments变量来收集这些。让我们看看我们的意思:

function add(first, second, ...remaining) {
  return first + second;
}

现在,以上只是总结了参数firstsecond。这意味着调用它add(1,2)add(1,2,3, 4)将产生相同的结果。要解决此问题,我们将键入:

function add(first, second, ...remaining) {
  return first + second + remaining.reduce((acc, curr) => acc + curr, 0);
}

以上意味着我们正在修复问题并使用所有输入参数。

如前所述,使用 rest 参数,即添加前面...作为收集剩余参数的一种方式,是我们命名它们并使其更明确地表明我们想要使用它们的一种方式。arguments至少从 ES5 开始就已经存在,但我认为鲜为人知。

-3- 字符串插值

你见过这样的声明吗?

class Product {
 constructor(name, description, price) {
   this.name = name;
   this.description = description;
   this.price = price;
 }

 getDescription() {
   return " Full description \n" + 
   " name: " + this.name + 
   " description: " + this.description

 }
}

我当然是在谈论getDescription()方法,一个冗长的、多行的、难以阅读的语句。这是大多数编程语言中的现实。在某些语言中还可以使用字符串插值,幸运的是,JavaScript 也不例外。我们可以把我们的getDescription()方法变成如下:

getDescription() {
   return `Full description \n: 
   name: ${this.name}
   description ${this.description}
   `;

 }

所以双反引号`是我们用来定义多行字符串的。我们还使用${}插值。希望你的世界现在好多了:)

-4- 速记属性

您可能在不知道它的情况下使用它。在 ES5 中,您必须编写以下内容:

function createCoord(x, y) {
  return {
    x: x,
    y: y
  }
}

在 ES6 及更高版本中,:如果它具有相同的名称,您可以省略右侧的内容,如下所示:

function createCoord(x, y) {
  return {
    x,
    y
  }
}

看起来不那么杂乱了对吧?

-5- 方法属性

这就是定义指向对象中方法的属性的方式。考虑以下 ES5 示例:

const math = {
  add: function(a,b) { return a + b; },
  sub: function(a,b) { return a - b; }, 
  multiply: function(a,b) { return a * b; }
}

您实际上并不需要拥有add:ES6 及更高版本的全部业务。你可以像这样输入它:

const math = {
  add(a,b) { return a + b; },
  sub(a,b) { return a - b; },
  multiply(a,b) { return a * b; }
}

-6- 解构:Destructuring

解构是关于你自己作为开发人员的头脑清醒。

对象解构

考虑以下代码:

function handle(req, res) {
 const name = req.body.name;
 const description = req.body.description;
 const url = req.url;

 log('url endpoint', url);

 // lots of logic happening
 dbService.createPerson( name, description )
}

无论如何,上面的代码并不完美,但它确实代表了我们想要从不同级别的对象中挖掘数据的情况。你问什么问题?好吧,如果我不必声明所有这些变量并保存一些击键怎么办?你可以这样做:

function handle(req, res) {
 const { body: { name, description }, url }, = req;

 log('url endpoint', url);

 // lots of logic happening
 dbService.createPerson( name, description )

在上面你看到三行如何变成一。

数组解构

这不限于对象。它也可以在数组上完成。考虑以下代码:

const array = [1,2,3,4,5,6];

const a = array[0];

const c = array[2];

这可以以更优雅的方式完成,如下所示:

const array = [1,2,3,4,5,6];
const [a, ,c, ...remaining] = arr;

// remaining = [4,5,6]

我们可以通过上述模式匹配从数组中取出值。如果我们想跳过我们输入, ,的内容,作为奖励,我会添加一个 REST 语句来获取剩余的项目。

参数匹配

我们也可以对函数及其参数执行此操作。当函数中有超过 2-3 个参数时,收集对象中的所有参数已成为事实上的标准,因此您会得到如下所示的函数:

function doSomething(config) {
  if(config.a) { ... }
  if(config.b) { ... }
  if(config.c) { ... }
}

更好的方法是:

function doSomething({ a, b, c }) {
  if(a) { ... }
  if(b) { ... }
  if(c) { ... }
}

-7- 数组方法

ES6 带来了一大堆可用的数组方法,例如:

  • find(), 在列表中找到一个项目 else null
  • findIndex(), 找到项目的索引
  • some(), 对于列表中的至少一项,谓词是否为真
  • includes(), 是列表​​的项目部分

考虑以下代码以了解其用法:

const array = [{ id: 1, checked: true }, { id: 2 }];
arr.find(item => item.id === 2) // { id: 2 }
arr.findIndex(item => item.id === 2) // 1
arr.some(item => item.checked) // true

const numberArray = [1,2,3,4];
numberArray.includes(2) // true

-8- Promises + Async/Await

如果你已经在这个街区呆了一段时间,你可能还记得我们只有回调的时候,像这样:

function doSomething(cb) {
  setTimeout(() =>  {
    cb('done')
  }, 3000)
}

doSomething((arg) => {
 console.log('done here', arg);
})

我们用它来处理一些操作是异步的并且只需要时间来完成的事实。然后我们得到了人们开始使用的 promise 库,最终我们得到了该语言的原生支持。所以现在我们可以做这样的事情:

function doSomething() {
  return new Promise((resolve, reject) => {
    setTimeout(() =>  {
      resolve('done')
    }, 3000)
  })
}

doSomething().then(arg => {
 console.log('done here', arg);
})

我们甚至可以链接整个体验,这样我们就可以进行如下调用:

getUser()
  .then(getOrderByUser)
  .then(getOrderItemsByOrder)
  .then(orderItems => {
    // do something with order items
  })

Async/await

然后我们得到了 async/await,生活变得更加辉煌。考虑上面的例子,现在 Promises 变成了这样:

async function getItems() {
  try {
    const user = await getUser();
    const order = await getOrderByUser(user);
    const items = await getOrderItemsByOrder(order);
    return items;
  } catch(err) {
    // handle error here, the suggestion to return something or rethrow
  }
}

getItems().then(items => {
  // do something with order items
})

我们得到一个看起来同步的异步代码。:)

 -9- 模块

几乎任何编码语言都支持模块的概念。将代码分成许多不同文件的能力,这些文件也是自包含单元的文件,即所谓的模块。考虑以下代码:

// math.js

export function add(a,b) { return a + b; }
export function sub(a,b) { return a - b; }

export default (a,b) => a * b;

// main.js
import mult, { add, sub } from './math';

mult(2, 4) // 8
add(1,1)   // 2
sub(1,2)   // -1

上面我们使用export关键字来表示这些构造add并且sub对于导入此模块的任何模块都是公开可用的。如果我们只导入它,export default关键字就是我们得到的。在main.js我们将默认值导入为具有名称时mult,我们还专门挑选出方法add()sub()

-10- 箭头函数 + 词法this

在本文中我一直在使用箭头函数,它只是另一种函数符号。过去我们只能写这样的函数:

function printArray(arr) {
 // do something
}

现在我们可以将其定义为:

const printArray = (arr) => {
 // do something
}

一行函数

我们还可以将函数定义为单行:

const add = (a,b) => a + b

这自动意味着我们执行操作并返回结果。我们可以做同样的事情并返回一个对象,我们的语法就变成了:

const create = (a,b) = > ({ x: a, y: b })

词法 this
我们曾经面临的问题是不知道是什么this。考虑以下问题:

let array = [1,2,3];

function sum() {
  this.total = 0;

  arr.forEach(function(item) {
    this.total+= item;  // `this` is the inner functions `this`, BAD
  })
  return total;
} 

this在上面的情况下点错里面的forEach. 我们过去解决这个问题的方法是:

function sum() {
  this.total = 0;
  var self = this;

  arr.forEach(function(item) {
    self.total+= item;  // now we are using `self`, it solves it but feels hacky
  })
  return total;
} 

箭头函数解决了这个问题,不再self,所以现在代码如下所示:

function sum() {
  this.total = 0;

  arr.forEach((item) => {
    this.total+= item;  // all is well `this` points to outer function
  })
  return total;
} 

赢了!

概括

关于 ES6 及更高版本,我还有更多可以提及的内容,但我只是想向您展示我认为您今天应该采用的我的最爱 🙂

现代 JavaScript,你应该使用的 10 件事,从今天开始
标签: