关于一些我不知道的 js 的东西

本文翻译自 https://air.ghost.io/js-things-i-never-knew-existed/ ,作者 Nick, 翻译:Thomas Chan

那天我通读了一遍 MDN 文档然后发现了一些我从来不知道的功能和 API。我简单列了一些有用的没用的 - 看来 js 永远学不完啊。

Label 语句

我从来不知道 js 还能给 for 循环和代码块命名…! 命名可以被使用在 for 循环里的 break, continue 或者代码块里的 break 后边。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

1
2
3
4
5
6
7
8
9
10
11
12
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 也可以像这样写一个自执行函数:

1
2
3
4
5
6
7
8
9
void function iife() {
console.log('hello');
}();

// 等价于...

(function iife() {
console.log('hello');
})()

有一点不好是 void 执行表达式相当于 void (undefined)!

1
2
3
4
5
6
7
8
9
10
11
const word = void function iife() {
return 'hello';
}();

// word 等于 "undefined"

const word = (function iife() {
return 'hello';
})();

// word 等于 "hello"

void 也可以跟 async 一起用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 的解释:

逗号运算符从左到右执行每个表达式,并且返回最后一个表达式的值。

1
2
3
4
5
6
7
8
9
10
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 在返回布尔值之前:

1
2
3
4
5
6
7
8
9
10
11
const type = 'man';

const isMale = type === 'man' ? (
console.log('Hi Man!'),
true
) : (
console.log('Hi Lady!'),
false
);

console.log(`isMale is "${isMale}"`);

译者注:逗号运算符在实际写代码中不太常用,因为代码是写给人看的,你可以在压缩后的代码里看到大把大把的逗号运算。

国际化 API

国际化还没有完全完善,不过现在绝大部分浏览器已经支持。其中我最喜欢的一个功能是日期的格式化,看例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
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,我很喜欢!

1
2
3
4
5
6
7
8
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 也可以用来展开数组(译者注:这真是挺鸡肋的...):

1
2
3
4
5
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(...)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 你好!

avatar

Thomas Chan

年轻就是暴躁,年轻就是不安分,年轻就是发脾气