关于一些我不知道的 js 的东西
本文翻译自 https://air.ghost.io/js-things-i-never-knew-existed/ ,作者 Nick, 翻译:Thomas Chan
那天我通读了一遍 MDN 文档然后发现了一些我从来不知道的功能和 API。我简单列了一些有用的没用的 - 看来 js 永远学不完啊。
Label 语句
我从来不知道 js 还能给 for
循环和代码块命名…! 命名可以被使用在 for
循环里的 break
, continue
或者代码块里的 break
后边。
loop1: // 命名 "loop1"
for (let i = 0; i < 3; i++) { // "loop1"
loop2: // 命名 "loop2"
for (let j = 0; j < 3; j++) { // "loop2"
if (i === 1) {
continue loop1; // 继续 "loop1"
// break loop1; // 结束 "loop1"
}
console.log(`i = ${i}, j = ${j}`);
}
}
/*
* # Output
* i = 0, j = 0
* i = 0, j = 1
* i = 0, j = 2
* i = 2, j = 0
* i = 2, j = 1
* i = 2, j = 2
*/
下边是给代码块命名的例子,在代码块里只能使用 break
。
foo: {
console.log('one');
break foo;
console.log('this log will not be executed');
}
console.log('two');
/*
* # Output
* one
* two
*/
“void” 运算符
我以为我了解所有的运算符直到我看见这个 1996 就已经在 js 里的运算符。所有的浏览器都支持 void
,这个运算符很好理解,引用 MDN 的解释:
void
运算符执行后边给出的表达式并且返回undefined
。
所以用 void
也可以像这样写一个自执行函数:
void function iife() {
console.log('hello');
}();
// 等价于...
(function iife() {
console.log('hello');
})()
有一点不好是 void
执行表达式相当于 void (undefined)!
const word = void function iife() {
return 'hello';
}();
// word 等于 "undefined"
const word = (function iife() {
return 'hello';
})();
// word 等于 "hello"
void
也可以跟 async
一起用:
void async function() {
try {
const response = await fetch('air.ghost.io');
const text = await response.text();
console.log(text);
} catch(e) {
console.error(e);
}
}()
// or just stick to this :)
(async () => {
try {
const response = await fetch('air.ghost.io');
const text = await response.text();
console.log(text);
} catch(e) {
console.error(e);
}
})();
逗号运算符
读了文档才知道以前并不是都了解了。看 MDN 的解释:
逗号运算符从左到右执行每个表达式,并且返回最后一个表达式的值。
function myFunc() {
let x = 0;
return (x += 1, x); // 等价于 ++x;
}
y = false, true; // console 里打印出来 true
console.log(y); // false
z = (false, true); // console 里打印出来 true
console.log(z); // true
跟三目运算符一起用
因为逗号运算符返回最后一个表达式的值这个特性,在三目运算符里你就可以在返回之前执行 n 个表达式,下边的例子里我放了一个 console.log
在返回布尔值之前:
const type = 'man';
const isMale = type === 'man' ? (
console.log('Hi Man!'),
true
) : (
console.log('Hi Lady!'),
false
);
console.log(`isMale is "${isMale}"`);
译者注:逗号运算符在实际写代码中不太常用,因为代码是写给人看的,你可以在压缩后的代码里看到大把大把的逗号运算。
国际化 API
国际化还没有完全完善,不过现在绝大部分浏览器已经支持。其中我最喜欢的一个功能是日期的格式化,看例子:
const date = new Date();
const options = {
year: 'numeric',
month: 'long',
day: 'numeric'
};
const formatter1 = new Intl.DateTimeFormat('es-es', options);
console.log(formatter1.format(date)); // 22 de diciembre de 2017
const formatter2 = new Intl.DateTimeFormat('en-us', options);
console.log(formatter2.format(date)); // December 22, 2017
管道操作符
写这篇文章的时候只有 Firefox 58+ 支持(要开启实验性 API),不过 Babel 已经提议了一个转换插件。写起来很像 bash,我很喜欢!
const square = (n) => n * n;
const increment = (n) => n + 1;
// 不使用管道符
square(increment(square(2))); // 25
// 使用管道符
2 |> square |> increment |> square; // 25
值得注意的几个
原子操作
多个共享内存的线程能够同时读写同一位置上的数据。原子操作会确保正在读或写的数据的值是符合预期的,即下一个原子操作一定会在上一个原子操作结束后才会开始,其操作过程不会中断。常用在线程之间保持数据同步,比如浏览器主线程和 WebWorker。
我很喜欢 Java 里的原子操作。我觉得等有更多的人把繁重操作从主线程移到 WebWorker 的时候这个功能才会用的比较多吧。
Array.prototype.reduceRight
好吧我从来没见用过这个函数,基本上就是 Array.prototype.reduce()
+ Array.prototype.reverse()
,而且这个操作很少见。reduceRight
也可以用来展开数组(译者注:这真是挺鸡肋的...
):
const flattened = [[0, 1], [2, 3], [4, 5]].reduceRight(function(a, b) {
return a.concat(b);
}, []);
// flattened array is [4, 5, 2, 3, 0, 1]
setTimeout() 参数
知道了这个可能会让我少些一两个 .bind(...)
。
setTimeout(alert, 1000, 'Hello world!');
/*
* # Output (alert)
* Hello World!
*/
function log(text, textTwo) {
console.log(text, textTwo);
}
setTimeout(log, 1000, 'Hello World!', 'And Mars!');
/*
* # Output
* Hello World! And Mars!
*/
结语
希望你在这个简短的列表里像我一样学到了一点新的东西。顺便给 Mozilla 的新 MDN 网站打 call,我觉得比以前好看多了 - 通读一遍花的时间比我想的要多的多。
新年快乐!2018 你好!