对ECMAScript的研究-----------引用
ECMAScript 新特性与标准提案
一:ES 模块
第一个要介绍的 ES 模块,由于历史上 JavaScript 没有提供模块系统,在远古时期我们常用多个 script 标签将代码进行人工隔离。但得益于浏览器和 Node.js 对于 ES 标准的讨论统一,现在我们可以在浏览器中直接书写 ES 模块语法。比如我们新建一个 lib.mjs 文件在其中导出一个函数,那么在 main.mjs 中我便可以直接导入使用它。
// lib.mjs
export const repeat = (string) => `${string} ${string}`;
// main.mjs
import {repeat} from './lib.mjs';
repeat('#io18');
而在浏览器中我们可以用 type=”module” 引入 ES 模块,我们还可以引入一个 JavaScript 文件用于兼容不支持 ES 模块写法的浏览器。加上 rel=”modulepreload” 我们可以告诉浏览器预加载一些公共库与代码。
// 浏览器
<script type="module" src="/mypath_to_js_module.mjs"></script>
<script nomodule src="fallback.js"></script>
// preload
<link rel="modulepreload" href="lib.mjs" >
上述的写法中都用到了 mjs 后缀,然而在浏览器中引用 ES 模块这种做法并不是强制的,但在 Node 实验性新特性中 mjs 是必须的。
node --experimental-modules main.mjs
兼容性如下
二:数字分隔符
给到你一串很长的数字,如何快速辨别其数值?
1000000000000
1019436871.42
我们换个写法,是不是就明确了不少:
1_000_000_000_000
1_019_436_871.42
对于非十进制数值,ES 允许我们同样用下划线进行区分
// 十六进制
0b01001001_00101111_01001111
0x23_69_6F_31_38
然而不幸的是这仍是一个处于 Stage 2 阶段的提案,但幸好我们有 Babel。兼容性如下:
三:BigInt
在 JavaScript 中安全整数范围是多少,console.log 一下。在此之前,我们若要操作超出安全整数范围的数值,结果正确性将不被得到保证,同样的问题也曾发生在 Node 上,曾有一个 issue 直指由于 Node 会偶发性给多个文件/文件夹赋值相同 inode 数。
对于超出了 Number 能够表示的安全整数范围的整数操作,我们现在可以使用 BigInt 了。虽然有很多 polyfill 支持,但现在我们得到官方支持了。
console.log(Number.MIN_SAFE_INTEGER); // 9007199254740991
console.log(Number.MAX_SAFE_INTEGER); // -9007199254740991
// BigInt 可以直接使用,也可以在整数值后面加上n用以表示属于 BigInt 类型
BigInt(Number.MAX_SAFE_INTEGER) + 2n;
// → 9007199254740993n 正确
1234567890123456789 * 123;
// → 151851850485185200000 错误结果
1234567890123456789n * 123n;
// → 151851850485185185047n 正确
42n === BigInt(42);
typeof 123n; // 'bigint'
BigInt(1.5);
// → RangeError
BigInt('1.5');
// → SyntaxError
兼容性如下:
四:Async Iterator/Generator
我们可能习惯了这样操作一段数据读取:
const print = (readable) => {
readable.setEncoding('utf8');
let data = '';
readable.on('data', (chunk) => {
data += chunk;
});
readable.on('end', () => {
console.log(data);
})
}
const fs = require('fs');
print(fs.createReadStream('./file.txt'));
但好消息是 await 支持 for-each-of 了,于是我们可以这样写了:
async function print(readable) {
readable.setEncoding('utf8');
let data = '';
for await (const chunk of readable) {
data += chunk;
}
console.log(data);
}
const fs = require('fs');
print(fs.createReadStream('./file.txt'));
兼容性
五:正则匹配与字符串操作方式
现在我们来看看 dotAll 模式。字符串模版我们都用过,比如要匹配出下面的 Hello world 我们该怎么做?
const input = `
Hi, Fliggy. Hello
world.
`;
/Hello.world/u.test(input); // false
我们可能会想到.可以表示任意字符,但在这里不行,因为匹配不上换行符。于是我们可以这样做:
/Hello[\s\S]world/u.test(input); // 所有空格和所有非空格匹配
/Hello[^]world/u.test(input); // 所有非空匹配
接下来要介绍的是 Name Capture,他的作用在于将从前我们需要通过下标获取的正则匹配结果通过显式命名方法进行匹配,例如原来我们这样匹配日期:
const pattern = /(\d{4})-(\d{2})-(\d{2})/u;
const result = pattern.exec('2017-07-10');
// result[0] === '2017-07-10'
// result[1] === '2017'
// result[2] === '07'
// result[3] === '10'
现在我们可以这样写:
const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = pattern.exec('2017-07-10');
// result.groups.year === '2017'
// result.groups.month === '07'
// result.groups.day === '10'
对于异常复杂的正则表达式,新特性写法的优势得以体现。
第三个特性来自 Unicode 字符匹配。现在 ES 提供两种简便的匹配方式,\p{…} 用于匹配非二进制 Unicode 字符,而 \P{…} 则取其相反。
/\p{Number}/u.test('①'); // true
/\p{Alphabetic}/u.test('雪'); // true
/\P{Number}/u.test('①'); // false
/\P{Alphabetic}/u.test('雪'); // false
/^\p{Math}+$/u.test('∛∞∉'); // true
/^\p{Script_Extensions=Hiragana}+$/u.test('ひらがな'); // true
以上所述几个方法的兼容性相同,当下 Edge 与 Firefox 还未支持。
第四个特性是字符串全匹配。通过 String matchall 特性,我们原来通过 while 循环匹配所有符合正则的写法可以直接通过 .matchAll 一次性搞定:
const string = 'Magic hex numbers: DEADBEEF CAFE 8BADF00D';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
let match;
// 旧方式
while (match = regex.exec(string)) {
console.log(match);
}
// 新方式
for (const match of string.matchAll(regex)) {
console.log(match);
}
新特性仍然处于 Stage 3,所以支持度比较感人,但社区已经有很多 polyfill 支持这种写法。
六:catch binding
正则总是让人难以理解,来说一个简单些的新特性—— try/catch。现在我们可以选择性的决定 catch 是否带上入参了。
try {} catch (e) {} // 以前
try {} catch {} // 现在
兼容性
七:trim
假设给你一串字符串,如果让你单独删除 hello 前部的空格或者尾部的空格,你会怎么做?
const string = ' hello ';
以前的话,你大概率得用正则来实现,而现在 trimStart 和 trimEnd 两个方法便可以完成操作。
string.trim(); // 'hello';
string.trimStart(); // 'hello ';
string.trimEnd(); // ' hello';
兼容性
八:Promise.prototype.finally
Promise 我们都写过,假设我们 fetch 一段数据,在结果回来之前我们需要加载 loading 动画,而结果回来后不管正确还是错误我们都需要去除这段动画。在原来,我们需要将相同的逻辑写在好几个地方(观察 isLoading = false; 写法):
let isLoading = true;
fetch(myRequest).then(function(response) {
var contentType = response.headers.get("content-type");
if(contentType && contentType.includes("application/json")) {
return response.json();
}
throw new TypeError("Oops, we haven't got JSON!");
})
.then(function(json) {
isLoading = false;
})
.catch(function(error) {
isLoading = false;
console.log(error);
});
而现在 Promise 原型方法上补充的 finally 可以给我们减少冗余代码。
let isLoading = true;
fetch(myRequest).then(function(response) {
var contentType = response.headers.get("content-type");
if(contentType && contentType.includes("application/json")) {
return response.json();
}
throw new TypeError("Oops, we haven't got JSON!");
})
.then(function(json) { /* ... */ })
.catch(function(error) { console.log(error); })
.finally(function() { isLoading = false; });
兼容性
九:对象解构
解构这个概念我们都不陌生,可能我们也一直在毫无感知的用着,但 ES2015 只给定了数组解构的标准,而直到2017年初针对对象的解构操作还处于 stage 3 阶段。
const person = {
firstName: 'Sebastian',
lastName: 'Markbåge',
country: 'USA',
state: 'CA',
};
const { firstName, lastName, ...rest } = person;
console.log(firstName); // Sebastian
console.log(lastName); // Markbåge
console.log(rest); // { country: 'USA', state: 'CA' }
// Spread
const personCopy = { firstName, lastName, ...rest };
console.log(personCopy);
// { firstName: 'Sebastian', lastName: 'Markbåge', country: 'USA', state: 'CA' }
在许多情况下,对象解构能为我们提供了一个更优雅的 Object.assign() 替代方案,例如合并两个对象:
const defaultSettings = { logWarnings: false, logErrors: false };
const userSettings = { logErrors: true };
// 老方式
const settings1 = Object.assign({}, defaultSettings, userSettings);
// 新方式
const settings2 = { ...defaultSettings, ...userSettings };
// 结果
// { logWarnings: false, logErrors: true }
兼容性
十:Class
最后我们来聊聊 JavaScript 中的 class。首先是字段定义,不再局限于(构造)函数中,我们可以这样定义属性 instanceProperty 和静态属性 staticProperty:
class MyClass {
instanceProperty = 0;
static staticProperty = 0;
}
其次是私有变量的定义与使用。在历史的长河中,JavaScript 一直缺少像其他编程语言「正规军」所有的私有变量概念,开发者长期以来都通过闭包来实现相关功能。而现在,标准赋予了 ES 这门语言拥有私有变量定义的可能性。
在使用方法上,如果需要在 class 中定义仅在类中可访问的属性,我们需要以#开头定义私有变量,就像下面这样:
class MyClass {
#foo; // 必须声明
constructor(foo) {
this.#foo = foo;
}
incFoo() {
this.#foo++;
}
}
至今为止,主流浏览器和 Node 均未实现该特性。
后记
知乎上有个问题说的是「为什么那么多公司仍然在使用JDK6?」,作者困惑于 JDK11 都已发布但很多公司还在用着老旧的 Java 版本的现状;而反观 JavaScript(ECMAScript) 生态,在 ECMAScript2018 远未定稿之时,很多开发者便得心应手的用上了新语法产出代码,很多写法可能仍处于 Stage 3。Java 和 JavaScript 不仅在关系上类似于雷锋于雷峰塔,就在对待语言标准上,两边的开发者态度也是截然相反。
ECMAScript 的征程是星辰大海,跟上 TA 的脚步。
对ECMAScript的研究-----------引用的更多相关文章
- 对Webpack 应用的研究-----------------引用
对大多数 Web 应用来说,页面性能直接影响着流量.这是一个经常为我们所忽视的事实.用户长时间的等待流失的不仅仅是跳出率.转化率,还有对产品的耐心和信赖.很多时候我们没有意识到性能问题,那是因为平常开 ...
- 对JS继承的研究--------------引用
问:类继承和原型继承不是同一回事儿吗,只是风格选择而已? 答:不是! 类继承和原型继承不论从本质上还是从语法上来说,都是两个截然不同的概念. 二者之间有着区分彼此的本质性特征.要完全看懂本文,你必须牢 ...
- 对React性能优化的研究-----------------引用
JSX的背后 这个过程一般在前端会称为“转译”,但其实“汇编”将是一个更精确的术语. React开发人员敦促你在编写组件时使用一种称为JSX的语法,混合了HTML和JavaScript.但浏览器对JS ...
- 对abel 转译 class 过程的研究----------------------引用
作为当下最流行的 JavaScript 编译器,Babel 替我们转译 ECMAScript 语法,而我们不用再担心如何进行向后兼容. 零.前言 虽然在 JavaScript 中对象无处不在,但这门语 ...
- 对vue-router的研究--------------引用
pushState/replaceState/popstate 解析 HTML5提供了对history栈中内容的操作.通过history.pushState/replaceState实现添加地址到hi ...
- 对GraphQL-BFF:微服务背景下的前后端数据交互方案的研究-------引用
随着多终端.多平台.多业务形态.多技术选型等各方面的发展,前后端的数据交互,日益复杂. 同一份数据,可能以多种不同的形态和结构,在多种场景下被消费. 在理想情况下,这些复杂性可以全部由后端承担.前端只 ...
- 对 Promises/A+ 规范的研究 ------引用
作为 Modern JavaScript 基础设施的一部分,Promises 对前端开发者而言异常重要.它是 async/await 语法的基础,是 JavaScript 中处理异步的标准形式.并且, ...
- 对webview的研究--------引用
简要的说,webview能够在移动应用中开辟出一个窗口,在里面显示html页面,css以及js代码也可以被解析执行,它使用的是我们熟悉的webkit内核.android和ios都有相应的API,所以写 ...
- 对React的研究-------------引用
DOM 的全称是 Document Object Model (文档对象模型) 响应式 UI const ThinkerWithHat = ({ hat }) => ( <div> ...
随机推荐
- python3实现自动化框架robotframework(最新)
# python3.6及以上版本兼容RIDE1.7.3版本由于最近RIDE1.7.3的版本改进,RIDE这个版本对高版本的wxpython兼容很好,python3.6及以上版本都可以顺利运行RIDE为 ...
- LeetCode.1010-歌曲总长度可被60整除的对数
这是小川的第377次更新,第405篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第239题(顺位题号是1010).在歌曲列表中,第i首歌曲的持续时间为[i]秒. 返回其总 ...
- Matlab学习笔记1—MATLAB基础知识
1.1 MATLAB系统环境 1.MATLAB操作界面的组成 (1)MATLAB主窗口 (2)命令行窗口:命令行窗口用于输入命令并显示命令的执行结果. (3) 当前文件夹窗口 如何设置当前文件夹呢? ...
- SSM项目——乐淘商城话述1.0
乐淘商城 项目介绍 淘淘网上商城是一个综合性的B2C平台,类似京东商城.天猫商城.会员可以在商城浏览商品.下订单,以及参加各种活动.管理员.运营可以在平台后台管理系统中管理商品.订单.会员等.客服可以 ...
- 【Qt开发】 数字转QString格式化
1 想要获得001 002 这样的数字 QString b=QString("%1").arg(i, 3, 10, QChar('0')); QStringList list; ...
- 【神经网络与深度学习】在Windows8.1上用VS2013编译Caffe并训练和分类自己的图片
最近想熟悉一下深度学习,体验了一下Caffe,简单写写训练和分类的过程: 1.下载Caffe VS2013工程:https://github.com/Microsoft/caffe 2. 解压并用VS ...
- 【VS开发】【图像处理】Pleora推出iPORT CL-U3外置抓帧器
全球领先的高性能视频接口产品供应商Pleora科技公司近日宣布推出可将Camera Link®摄像头转化为USB3Vision™摄像头的首个产品iPORT CL-U3外置抓帧器,树立了另一个行业里程碑 ...
- 【miscellaneous】星光级超低照度摄像机技术分析
低照度摄像机采用了超灵敏度图像传感器和独有的电子倍增和噪点控制技术能够极大地提高摄像机的灵敏度,并且具备24小时全彩色实时效果,绝无普通低照度摄像机出现的拖尾现象,以满足对夜间高品质监控的需求. ...
- Revo Uninstaller Pro - 真正彻底卸载软件不留垃圾的强大神器!(清理安装残留文件/注册表)
大家都知道 Windows 在卸载软件时总是不够彻底,系统C盘总会留下大量难以辨别和清理的垃圾文件和临时文件,时间长了注册表也会变得非常臃肿,不仅浪费硬盘空间,而且也会明显拖慢系统响应和启动速度. R ...
- windows jenkins 发布 springboot项目脚本
windows jenkins 发布 springboot项目脚本 1.关闭现有程序 (按端口关闭) [与按应用关闭 二选一] @echo off for /f "tokens=1-5&q ...