ES2015引入了许多功能,例如箭头功能,用于对象创建和继承的类语法let
以及const
,以及许多其他新功能。在接下来的几年中,将在语言和标准库中引入更多的强大功能。ES2016是次要修订,具有新功能,例如将includes
函数引入数组和指数运算符。ES2017引入了更多功能,如Object.values
and和Object.entries
and字符串函数,如padStart
and padEnd
和async
and和await
。这些便捷的功能为JavaScript开发人员带来了更多便利,从而使JavaScript应用程序的开发更加轻松。
ES2016功能
Array.includes
Array.includes
检查数组中是否存在项目。它需要一个数字或字符串,函数可以将其作为第一个参数进行比较,将索引从中进行搜索作为第二个参数。第二个参数可以是正数或负数。
const array = [1,2,3];
const includesTwo = array.includes(2); // returns true
我们也可以从负索引开始搜索数组,然后从计算索引开始搜索函数,计算索引是数组的长度加上第二个参数。因此,如果我们写:
array.includes(2, -2);
然后该includes
函数将从索引开始搜索。3 +(-2).
这意味着array.includes(2, -2);
应该返回true
。如果您传入的绝对数大于长度,那么将搜索整个数组。
该includes
函数还添加到TypedArray类型,例如Int8Array或Uint8Array。
指数算子
指数运算符是ES2016的另一个新功能。指数运算符用表示**
。这是用于计算指数值的新语法,是该Math.pow
函数的替代方法。例如,要将2乘以3的幂,我们可以这样写:
2**3
这是8。请注意,在JavaScript中,当我们将指数运算符与像-
这样的一元运算符结合使用时,就不可能编写含糊的表达式,因此-2**2
在JavaScript中,类似的东西是无效的。但是,-(2**2)
之所以有效是因为它的含义是明确的,因为指数在括号中并且负号在外面,因此我们知道该值为-4。
我们可以通过写以下命令来强制求幂表达式的基数为负数:
(-2)**2
因此,这意味着base
必须在括号中。
ES2017功能
对象值
将Object.values
让我们获得与对象的值的数组的数组。值的返回顺序与for...in
循环提供的顺序相同,只是Object.values
不返回原型链中的值。
例如,我们可以这样写:
const obj = { a: 1, b: 2 };
console.log(Object.values(obj)); // [1, 2]
const obj = { 0: 'd', 1: 'e', 2: 'f' };
console.log(Object.values(obj)); // ['d', 'e', 'f']
const obj2 = { 100: 'd', 2: 'e', 7: 'f' };
console.log(Object.values(obj2)); // ['e', 'f', 'd']
console.log(Object.values('abc')); // ['a', 'b', 'c']
如我们所见,Object.values
可以使用对象和字符串。如果键是数字,则将它们与键按升序返回,obj2
如上例所示。对于字符串,它返回字符串中各个字符的数组。
Object.entries()
该Object.entries
函数返回一个数组,每个条目都是其各自数组中的键值对。for...in
除了Object.values
不返回原型链中的值外,条目将按循环提供的顺序返回。与任何对象一样,我们可以对数组进行排序,以按sort
函数所需的顺序获取条目。
例如,我们可以这样写:
const obj = { foo: 1, bar: 2 };
console.log(Object.entries(obj)); // [ ['foo', 1], ['bar', 2] ]
const obj = { 0: 'x', 1: 'y', 2: 'z' };
console.log(Object.entries(obj)); // [ ['0', 'x'], ['1', 'y'], ['2', 'z'] ]
const obj2 = { 100: 'x', 2: 'y', 7: 'z' };
console.log(Object.entries(obj2)); // [ ['2', 'x'], ['7', 'y'], ['100', 'z'] ]
console.log(Object.entries('abc')); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
console.log(Object.entries(100)); // [ ]
const obj = { a: 1, b: 2, c: 3};
for (const [key, value] of Object.entries(obj)) {
console.log(`${key} ${value}`); // "a 1", "b 2", "c 3"
}
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`); // "a 1", "b 2", "c 3"
});
在上面的示例中,我们可以看到Object.entries
返回一个键-值对数组,每个条目作为一个数组,键是第一个元素,值是第二个元素。如果键是整数,则它们以升序排列。因此Object.entries(obj2)
返回[ ['2', 'x'], ['7', 'y'], ['100', 'z'] ]
。它也适用于以单个字符返回且以字符索引为键的字符串,因此键是字符串的索引,它是每个条目的第一个元素,单个字符是字符串的值,作为第二个字符返回。对于没有属性的对象,例如数字和布尔值,Object.entries
将返回一个空数组。
返回的数组Object.entries
可以转换为Map
对象。可以像下面的示例一样使用它:
const obj = { a: 1, b: 2 };
const map = new Map(Object.entries(obj));
console.log(map); // Map { a: 1, b: 2 }
String.padStart()
该padStart()
函数在字符串之前添加字符串的次数,直到达到您指定的长度。该函数有两个参数。第一个是字符串的目标长度。如果目标长度小于您的字符串的长度,则按原样返回字符串。第二个参数是您要添加填充的字符串。这是一个可选参数,默认为' '
未指定。
例如,我们可以编写以下代码:
'def'.padStart(10); // " def"
'def'.padStart(10, "123"); // "1231231def"
'def'.padStart(6,"123465"); // "abcdef"
'def'.padStart(8, "0"); // "00000def"
'def'.padStart(1); // "def"
请注意,每个字符串都使用第二个参数中的字符串填充到目标长度。第二个参数中的整个字符串可能并不总是包含在内。仅包括使函数填充字符串直至目标长度的部分。
String.padEnd()
该padEnd()
函数将字符串添加到字符串之后的次数增加,直到达到您指定的长度。该函数有2个参数。第一个是字符串的目标长度。如果目标长度小于您的字符串的长度,则按原样返回字符串。第二个参数是您要添加填充的字符串。这是一个可选参数,默认为' '
未指定。
例如,我们可以编写以下代码:
'def'.padEnd(10); // "def "
'def'.padEnd(10, "123"); // "def1231231"
'def'.padEnd(6,"123465"); // "defabc"
'def'.padEnd(8, "0"); // "def00000"
'def'.padEnd(1); // "def"
Object.getOwnPropertyDescriptors()
该Object.getOwnPropertyDescriptors()
函数返回对象的所有属性描述符。
例如,我们可以像下面的代码一样使用它:
const obj = {
a: 1
};const descriptors = Object.getOwnPropertyDescriptors(obj);
该descriptors
对象应具有:
{
a: {
configurable: true,
enumerable: true,
value: 1,
writable: true
}
}
异步并等待
使用async
和await
,我们可以缩短承诺代码。在async
和之前await
,我们必须使用该then
函数,然后将回调函数作为所有函数的参数then
。这使代码很长,因为我们有很多承诺。相反,我们可以使用async
and await
语法替换then
如下及其相关的回调。例如,我们具有使用Fetch API向后端发出请求的代码:
const APIURL = "http://localhost:3000";
const subscribe = async data => {
const response = await fetch(`${APIURL}/subscribers`, {
method: "POST",
mode: "cors",
cache: "no-cache",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
return response.json();
};
window.onload = () => {
nameForm.method = "post";
nameForm.target = "_blank";
nameForm.action = "";
nameForm.addEventListener("submit", async e => {
e.preventDefault();
const firstName = document.getElementById("firstName").value;
const lastName = document.getElementById("lastName").value;
const email = document.getElementById("email").value;
let errors = [];
if (!firstName) {
errors.push("First name is required.");
}
if (!lastName) {
errors.push("Last name is required.");
}
if (!email) {
errors.push("Email is required.");
}
if (!/\[^@\]+@\[^\.\]+\..+/.test(email)) {
errors.push("Email is invalid.");
}
if (errors.length > 0) {
alert(errors.join(" "));
return;
}
try {
const response = await subscribe({
firstName,
lastName,
email
});
alert(`${response.firstName} ${response.lastName} has subscribed`);
}
catch (error) {
alert(error.toString());
}
});
};
我们用替换了then
和回调await
。然后,我们可以将每个promise的解析值分配为变量。请注意,如果使用await
我们的Promise代码,则必须async
像上面的示例一样放入函数签名。为了捕获错误,而不是最后链接catch
函数,我们使用catch
子句来实现。此外,我们不会finally
在承诺结束时在底部链接函数以运行代码,而是在该finally
子句之后使用该catch
子句来实现。
在上面的代码中,我们获得了分配给变量的promise的解析值,而不是then
像上const response = await subscribe({...})
一行一样在函数的回调中获取值。
async
函数始终返回承诺,并且不能像使用承诺的任何其他函数一样返回其他任何内容。在上面的示例中,我们使用了基于承诺的Fetch API和async
和await
语法,表明与使用then
以回调函数作为参数传入的函数相比,可以用更短的方式链接承诺。
ES2016和2017为我们提供了便捷的功能,增强了ES2015中已经非常强大的语法糖和功能,这是对它的前身的重大改进。这两个版本的JavaScript使用新的Object,string和Array方法以及链接承诺的简写使JavaScript开发更加出色。