3

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

 1 year ago
source link: https://blog.p2hp.com/archives/9944
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在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 及更高版本,我还有更多可以提及的内容,但我只是想向您展示我认为您今天应该采用的我的最爱 🙂


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK