现代JavaScript,你应该使用的10个东西,从今天开始

86 阅读7分钟

Twitter上关注我,很高兴接受你对主题或改进的建议 /Chris

你可能对JavaScript完全陌生,也可能多年来只是零星地使用它。但有一点是清楚的--很多东西都发生了变化,有些功能你应该使用。这篇文章描述了我认为你应该每天使用的功能,如果你是认真研究JavaScript的话。

这里是视频版本。

资源

这些是我最喜欢的关于ES6+的资源。

-1- 展开运算符

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

展开数组

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

这是一种很好的、紧凑的书写方式。如果没有这个,做同样的事情将意味着做这样的事情。

NO Array spread

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 Object spread

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

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

-2-休息参数

休息参数是指将其余的参数收集到一个数组中。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);
}

上面的意思是我们正在修复这个问题,并使用所有的输入参数。

如前所述,使用其余参数,即在前面添加一个... ,作为收集其余参数的方式,是我们为它们命名的一种方式,使其更明确地表明我们要与它们一起工作。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; }
}

实际上你不需要从ES6及以后的整个add: 业务。你可以直接这样输入。

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(), 找到列表中的一个项目,否则为空
  • 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-承诺+异步/等待

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

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

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

我们用它来处理一些操作是异步的,需要时间来完成的事实。然后,我们得到了人们开始使用的承诺库,最后,我们在语言中得到了本地支持。所以现在我们可以做这样的事情。

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 关键字来表示这些结构addsub 对导入这个模块的任何模块都是公开可用的。export default 关键字是我们得到的,如果我们只是导入它。在main.js 中,我们导入默认的名称为mult ,我们还特别挑选了方法add()sub()

-10- 箭头函数+词法this

在这篇文章中我一直在使用Arrow函数,它只是另一种函数符号。在过去,我们只能这样写函数。

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 。考虑一下下面的问题。

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和前进,我还可以提到更多的东西,但我只想向你展示我最喜欢的东西,我认为你今天应该采用:)