我未曾见过的 JS 特性

我未曾见过的 JS 特性

大家好,又见面了,我是全栈君。

我未曾见过的 JS 特性

有一天我正在阅读 MDN 文档,发现了一些我之前压根没有意识到在 JS 中存在的特性和 API。这里我罗列了一些,不管它们是否有用,JS 的学习永无止境。

标记语句

有多少人知道在 JS 里你可以给 for 循环和语句块命名?反正我不知道…… 命名完新名称之后你可以在 for 循环中的 breakcontinue 之后、语句块中的 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}`);
   }
}

/* 
 * # 输出
 * 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('这句打印不会被执行');
}
console.log('two');

/*
 * # 输出
 * one
 * two
 */
复制代码

“void” 运算符

我一度以为我已经了解了所有的运算符,直到我看到了这一个。它从 1996 年 起就存在于 JS 了。所有的浏览器都支持,并且它也很容易理解,引用自 MDN:

void 运算符对给定的表达式进行求值,然后返回 undefined。

使用它,你可以换一种方式来写立即调用的函数表达式(IIFE),就像这样:

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"
复制代码

你也可以和 async 一起使用 void,这样你就能把函数作为异步代码的入口:

void async function() { 
    try {
        const response = await fetch('air.ghost.io'); 
        const text = await response.text();
        console.log(text);
    } catch(e) {
        console.error(e);
    }
}()

// 或者保持下面的写法

(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); // 等价于 return ++x;
}

y = false, true; // console 中得到 true
console.log(y); // false,逗号优先级低于赋值

z = (false, true); // console 中得到 true
console.log(z); // true,括号中整体返回 true
复制代码

配合 条件运算符

逗号运算符中的最后一个值作为返回给条件运算符的值,因此你可以在最后一个值前面放任意多个表达式。在下面的例子中,我在返回的布尔值之前放了打印语句。

const type = 'man';

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

console.log(`isMale is "${isMale}"`);
复制代码

国际化 API

即使在最有利的情况下,国际化还是很难做好。幸好还有一套大部分浏览器都支持得不错的 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 及以上版本通过传入启动参数来支持,不过 Babel 已经有一个针对它的 插件提议。它看起来应该是受到 bash 的启发,我觉得很棒!

const square = (n) => n * n;
const increment = (n) => n + 1;

// 不使用管道操作符
square(increment(square(2))); // 25

// 使用管道操作符
2 |> square |> increment |> square; // 25
复制代码

值得一提

Atomics

当数据被多个线程共享时,原子操作确保正在读和写的数据是符合预期的,即下一个原子操作一定会在上一个原子操作结束之后才会开始。这有利于保持不同线程间的数据同步(比如主线程和另一条 WebWorker 线程)。

我很喜欢如 Java 等其它语言中的原子性。我预感当越来越多的人使用 WebWorkers,将操作从主线程分离出来时,原子操作的使用会越来越广泛。

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!');

/*
 * # alert 输出
 * Hello World!
 */

function log(text, textTwo) {
    console.log(text, textTwo);
}

setTimeout(log, 1000, 'Hello World!', 'And Mars!');

/*
 * # 输出
 * Hello World! And Mars!
 */
复制代码

HTMLElement.dataset

在此之前我一直对 HTML 元素使用自定义数据属性 data-*,因为我不曾意识到存在一个 API 来方便地查询它们。除了个别的命名限制之外(见上面的链接),它的作用基本就是在 JS 中查询的时候允许你使用驼峰命名法(camelCase)来查询「减号-命名」(dash-case)的属性。所以属性名 data-birth-planet 在 JS 中就变成了 birthPlanet

<div id='person' data-name='john' data-birth-planet='earth'></div>
复制代码

查询:

let personEl = document.querySelector('#person');

console.log(personEl.dataset) // DOMStringMap {name: "john", birthPlanet: "earth"}
console.log(personEl.dataset.name) // john
console.log(personEl.dataset.birthPlanet) // earth

// 你也可以在程序中添加属性
personEl.dataset.foo = 'bar';
console.log(personEl.dataset.foo); // bar
复制代码

结束语

我希望你和我一样在这里学到了一些新知识。在此也赞一下 Mozila 新的 MDN 站点,看起来非常棒,我花了比想象中更多的时间来阅读文档。

修订: 修正几处命名并且为 async 函数添加 try, catch。感谢 Reddit!

2018 新年快乐!


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107722.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 使用PyPDF2模块处理PDF文件通用方法技巧

    使用PyPDF2模块处理PDF文件通用方法技巧基本概念:PDF和Word文档是二进制文件,除了文本之外还保存字体,颜色,布局等信息。处理PDF文件,使用PyPDF2模块,PyPDF2不能从PDF文档中提取图像、图表或其他媒体,但可提取文本,作为字符串返回。  读取PDF文件步骤:首先以读二进制模式打开PDF文件,然后将打开文件File对象传递给PyPDF2.PdfFileReader()函数,例如: …

    2022年6月23日
    58
  • 400错误请求什么意思_网页400错误怎么解决

    400错误请求什么意思_网页400错误怎么解决400错误请求怎么解决A400BadRequestErroroccurswhenarequestsenttothewebsiteserverisincorrectorcorrupt,andtheserverreceivingtherequestcan’tunderstandit.Occasionally,theproblemisont…

    2022年9月29日
    3
  • 国产数据库乱象_四代户户通怎么开户

    国产数据库乱象_四代户户通怎么开户其实这篇文章是我周末开始写的,写这篇文章的这个周末,我的很多时候都是在思考一个数据库国产化替代的建设方案,翻阅了大量的资料。今年正好是我参加工作后的第31个年头,工作的最初十年,我写了十年代码,从汇编、COBOL到C语言,写了几十万行代码;随后的十几年,我一直在帮助用户用好数据库,也在帮助Oracle推广RAC技术;2015年开始,我一边继续从事数据库优化的工作,一边在帮助客户如何从Oracle迁移到成本更低的数据库系统上。所以对国产数据库我一直有一种十分特殊的情感,这是一种爱恨交织的情感。所以今天最后用“

    2022年9月19日
    2
  • idea打包java项目生成jar_idea打包项目

    idea打包java项目生成jar_idea打包项目Idea打包java项目、点击加号Artifacts工件一定要双击加入到左侧再运行jar包java-jardemo.jar包名.jar

    2022年9月27日
    3
  • JAVA设计模式之单例模式

    本文继续介绍23种设计模式系列之单例模式。概念:  java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。  单例模式有以下特点:  1、单例类只能有一个实例。  2、单例类必须自己创建自己的唯一实例。  3、单例类必须给所有其他对象提供这一实例。  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例…

    2022年3月11日
    38
  • 史上最全 XMind 8 快捷键大全「建议收藏」

    史上最全 XMind 8 快捷键大全「建议收藏」对于那3名小学生在我背后鬼鬼祟祟小声议论的这件事,其实我是知晓的。但我还是将注意力集中在眼前的屏幕上,力求表现得尽可能好一些,毕竟这局的形势尚未明朗,胜负依旧难分。又是一阵剧烈的连续按键,对方英雄终于败在我的剑下。随着身后的小学生团队发出“哇”的一声惊叹,我感受到了他们向我投来近乎崇拜的目光。我早已习惯小学生们的艳羡,以及被他们赋予的“大神”称号,当然还有他们对我惯常的提问,“大哥哥,怎…

    2022年5月22日
    47

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号