javascripttip(3 部分系列)
1现代 JavaScript,你应该使用的 10 件事,从今天开始
2了解如何在 JavaScript 中使用循环
3如何在 JavaScript 中学习足够多的 RegEx 才能变得危险
您可能对 JavaScript 完全陌生,也可能多年来只是偶尔使用过它。不过有一件事很清楚——很多地方都变了,有些功能你应该使用。如果你认真对待 JavaScript,这篇文章描述了我认为你应该每天使用的特性
资源
这些是我最喜欢的 ES6+ 资源:
ES6 特性
MDN
-1- 展开运算符
这被表示为...对象或数组之前的 a 并且完成了名称所说的内容,它将某些东西从结构变成了逗号分隔的列表。让我们证明这一点:
展开数组
let firstHalf = [ 'one', 'two'];
let secondHalf = ['three', 'four', ...firstHalf];
这是一种非常简洁的编写方式。没有这个就做同样的事情意味着做这样的事情:
NO阵列传播
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'
}
以困难的方式执行此操作将是我们遍历对象的所有属性:
没有物体传播
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- 休息参数
剩余参数是关于将剩余的参数收集到一个数组中。JavaScript 能够灵活处理您为其提供的输入参数的数量。通常有一个arguments收集这些的变量。让我们看看我们的意思:
function add(first, second, ...remaining) {
return first + second;
}
现在,以上仅总结了参数first和second。这意味着用add(1,2)or调用它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; }
}
你实际上不需要拥有add:ES6 及以后的全部业务。你可以像这样输入它:
const math = {
add(a,b) { return a + b; },
sub(a,b) { return a - b; },
multiply(a,b) { return a * b; }
}
-6- 解构
解构关乎您作为开发人员的精神健全。
对象解构
考虑以下代码:
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(), 在列表中找到一个项目,否则为 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- 承诺 + 异步/等待
如果你在这个街区呆了一段时间,你可能还记得我们只有回调的时候,就像这样:
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,生活变得更加美好。考虑上面的例子,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 和后续版本,我还有很多事情可以提,但我只想向您展示我认为您今天应该采用的我最喜欢的东西 :)