了解语言的新特性是非常重要的一件事。之前一直都搞不太明白ES6之后,JS版本命名的规范。网上很多人也没有弄得太清楚。在ES6之后,ECMAScript委员会决定换一种命名方式,也就是以年份来命名。现在我也简单总结了一下一些新的规范的内容,至于具体的提案大家可以在github上看到相关内容。
Array.prototype.includes
本质:语法糖
年份:2016
Array.prototype.includes 判断数组是否包含对应的值。
原本写法
if(arr.indexOf(el) !== -1){
// do something
}
新写法
if(arr.includes(el,bl)){
// do something
}
Exponentiation Operator
本质:语法糖
年份:2016
Exponentiation Operator 幂运算符。计算幂运算。
原本写法
let mi = Math.pow(2,3)
// 8
新写法
let mi = 2 ** 3;
// 8
幂运算符号,更便捷的写法,也是和其他语言接轨。
Object.values / Object.entries
本质:语法糖
年份:2017
Object.values / Object.entries Object对象上的两个方法,类似于Object.keys。返回的都是相应的数组。
String.prototype.padStart / String.prototype.padEnd
年份:2017
String.prototype.padStart / String.prototype.padEnd 在String原型上新添加了两个方法。提案上说,因为这两个方法用的很多,但是现在很多实现实际上很低效。因此很有必要提出。同时,原本提案叫padLeft和padRight之后的一次会议修改成现在的名字。
效果很简单就是,给字符串填充字符达到指定长度,默认填充的是空格。同时注意,他返回的是一个新的字符串而不是在原本字符串上进行修改。另一点,第一个参数是maxLength,所以当你的填充字符是多个的时候。他只会填充到指定长度,不会在继续填充了。
// String.prototype.padStart( maxLength [ , fillString ] )
"liwei".padStart(10);
// " liwei"
"liwei".padStart(10,"o");
// "oooooliwei"
// String.prototype.padEnd( maxLength [ , fillString ] )
"liwei".padStart(10);
// "liwei "
"liwei".padStart(10,"o1");
// "liweio1o1o"
Object.getOwnPropertyDescriptors
年份:2017
Object.getOwnPropertyDescriptors(obj) 返回指定对象 obj 上自有属性对应的属性描述符。这个方法的引入是为了解决两个对象之间复制的问题。原有的Object.assign
方法使用了简单的get和set方法来复制其键为key的属性,这就导致了对象的一些属性没有办法复制(比如Object.defineProperties方法操作的那些)。比如getter,setter,不可写,枚举
等属性就无法被Object.assign
复制。
const obj = {
[Symbol('foo')]: 123,
get bar() { return 'abc' },
};
console.log(Object.getOwnPropertyDescriptors(obj));
// Output:
// { [Symbol('foo')]:
// { value: 123,
// writable: true,
// enumerable: true,
// configurable: true },
// bar:
// { get: [Function: bar],
// set: undefined,
// enumerable: true,
// configurable: true } }
拷贝对象属性
const source = {
set foo(value) {
console.log(value);
}
};
console.log(Object.getOwnPropertyDescriptor(source, 'foo'));
// { get: undefined,
// set: [Function: foo],
// enumerable: true,
// configurable: true }
const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
console.log(Object.getOwnPropertyDescriptor(target2, 'foo'));
// { get: undefined,
// set: [Function: foo],
// enumerable: true,
// configurable: true }
Trailing commas in function parameter lists and calls(尾随逗号)
年份:2017
尾随逗号,意思是允许在函数参数和函数调用时参数最后写一个逗号。这主要是因为参数列表很多时候都会在格式化时,把参数列表格式化成一行一行的。而这样就导致在你需要添加一个新参数的时候,需要修改两行。这就会在git等版本管理系统当中造成你修改了两行的情况。因此加入了这个新的特性来优化。
async/await
本质:语法糖
年份:2017
async/await 函数,本质上就是Promise的一个语法糖,能够让你更顺畅的去写Promise。同时也能让你很简单的通过try/catch进行错误处理。
原写法
new Promise((resolve,reject)=>{
//dosomething
resolve('1');
}).then((value)=>{
return value+'2';
}).then((value)=>{
return value+'3';
}).catch((err)=>{
console.log(err);
})
这样的写法虽然比原来的回调地狱要好很多了,但是依然不够直观。当我们有了async/await函数进行配合的时候,我们就能更轻松的编写异步函数了。
新写法
async function doSomething() {
const result = await getDataFromNet(); //从网络获取
return result;
}
async function doHere() {
try {
let a = await doSomething();
console.log(a);
} catch (error) {
console.log(error);
}
}
值得注意的是,要使用async标记的函数一定要在前面加await,而要用await关键字,一定要在async函数中。
本质上async函数返回的就是一个Promise的对象,你如果用await那么拿到的就是他resolve的值,如果没有用await那么你拿到的就是Promise他本身。因此,是可以配合使用Promise的相关方法的,比如。all,race等方法。
async function logPosts () {
try {
let user_id = await fetch('/api/users/username')
let post_ids = await fetch('/api/posts/${user_id}')
let promises = post_ids.map(post_id => {
return fetch('/api/posts/${post_id}')
}
let posts = await Promise.all(promises)
console.log(posts)
} catch (error) {
console.error('Error:', error)
}
}
Shared memory and atomics
年份:2017
这份提案主要是js的多线程相关的,为了实现线程间的数据交换,共享内存,原子操作。很复杂,感兴趣的请看这篇博文吧:
SharedArrayBuffer and Atomics - Web 的多线程并发编程