EcmaScript 10-今年的JavaScript(ES2019)

JS标准化已转换为一年的更新周期,从今年初开始是周年纪念的最佳时机-第十届EcmaScript!


ES 9是该规范当前版本


ES 10仍然是草案


到目前为止, 4 阶段 仅有一些建议。


第三阶段 -一打!


在我看来,其中最有趣的是类的私有字段, 脚本的shebang语法任意精度的数量对全局上下文的访问权动态导入



KDPV:黄色磁铁在监视器屏幕上刻有“ JS ES10”字样-来自kasper.green&elfafeya.art
图片提供者:kasper.green; 黄色磁铁:elfafeya.art和kasper.green


目录内容


五个阶段


阶段4-决赛


catch参数已成为可选的


Symbol().description -符号的描述的访问器


' EcmaScript' -改进了与JSON格式#的兼容性


.toString() -原型方法已更新


Object.fromEntries() -从成对的数组中创建一个对象Object.fromEntries() \ value ;


.flat().flatMap()是原型.flatMap()方法




阶段3-预发布


# -通过octotorp ,所有内容在班级中都是私有的


#!/usr/bin/env node -脚本的shebang语法 ;


BigInt() -一个新的原语,用于任意精度的数字


globalThis –一种访问全局上下文的新方法


import(dynamic) -动态导入


import.meta有关已加载模块#的元信息


JSON.stringify() -修复方法


RegExp弃用的功能


.trimStart().trimEnd() -原型字符串方法


.matchAll() -具有全局标志#的 .match()


结果




五个阶段


阶段 0Strawman Basting 一个想法,可以通过Babel- plugin实现。


阶段 1提案 提案可行性的验证。


第二阶段草案 草案开始制定规范。


阶段 3候选 候选预览规范。


阶段 4 ֍已完成今年规范最终版本已完成。




我们将只考虑 4 阶段 -事实上的标准。


第三阶段 -即将成为其中的一部分。





֍第四阶段


这些更改已经是标准的。


catch可选参数


https://github.com/tc39/proposal-optional-catch-binding


ES 10之前,即使未使用catch需要使用必需的参数来收集错误信息:


 function isValidJSON(text) { try { JSON.parse(text); return true; } catch(unusedVariable) { //    return false; } } 


Edge尚未升级到ES 10,并且可能因错误而崩溃。


ES 10版本开始,可以省略括号,并且catch将像try一样变成两滴水。



我的Chrome已更新为ES 10,在某些地方已更新为Stage 3 进一步的屏幕截图将来自Chrome


源代码
 function isValidJSON(text) { try { JSON.parse(text); return true; } catch { //   return false; } } 



访问符号链接描述


https://tc39.imtqy.com/proposal-Symbol-description/


可以使用toString()方法间接获得符号链接描述:


 const symbol_link = Symbol("Symbol description") String(symbol_link) // "Symbol(Symbol description)" 

ES 10开始,字符的描述属性为只读。 它使您无需手鼓跳舞就能获得符号的描述:


 symbol_link.description // "Symbol description" 

如果未指定描述,它将返回undefined


 const without_description_symbol_link = Symbol() without_description_symbol_link.description // undefined const empty_description_symbol_link = Symbol('') empty_description_symbol_link.description // "" 



与JSON兼容的EcmaScript字符串


https://github.com/tc39/proposal-json-superset


EcmaScript在其第十版之前声称JSONJSON.parse的子集,但事实并非如此。


JSON行可以包含非屏蔽行分隔符U+2028 LINE SEPARATOR和段落U+2029 PARAGRAPH SEPARATOR


ECMAScript排到第十个版本-不。


如果在Edge中使用字符串"\u2029"调用eval()
它的行为就像我们进行了换行一样-在代码中间:




使用ES 10系列-一切都很好:





原型.toString()方法的细化


http://tc39.imtqy.com/Function-prototype-toString-revision/


改变目标
  • 删除向后不兼容的要求:

如果实现无法创建满足这些条件的源代码字符串,则它必须返回一个字符串,eval将为该字符串引发语法错误的异常。

  • 阐明“功能等效”的要求;


  • 标准化内置函数和宿主对象的字符串表示形式;


  • 根据对象的“实际特征”阐明表示要求;


  • 确保字符串的解析包含与原始字符串相同的函数主体和参数列表;


  • 对于使用ECMAScript代码定义的函数,toString应该返回源文本的片段,从对应于相应语法构造的第一个标记的开头到最后一个标记的结尾;


  • 对于内置的功能对象,toString不应返回任何内容,而NativeFunction则应;


  • 对于未使用ECMAScript代码定义的被调用对象,toString必须返回NativeFunction;


  • 对于动态创建的函数(函数或生成器构造函数),toString必须合成源文本;


  • 对于所有其他对象,toString应该抛出TypeError异常。



 //   function () { console.log('My Function!'); }.toString(); // function () { console.log('My Function!'); } //     Number.parseInt.toString(); // function parseInt() { [native code] } //     function () { }.bind(0).toString(); // function () { [native code] } //     Symbol.toString(); // function Symbol() { [native code] } //     Function().toString(); // function anonymous() {} //    - function* () { }.toString(); // function* () { } // .call   ,   ,  Function.prototype.toString.call({}); // Function.prototype.toString requires that 'this' be a Function" 



使用Object.fromEntries()方法创建对象


https://github.com/tc39/proposal-object-from-entries


适用于Chrome


来自lodash_.fromPairslodash


 Object.fromEntries([['key_1', 1], ['key_2', 2]]) // {key_1: 1; key_2: 2} 



具有.flat().flatMap()一维数组


https://github.com/tc39/proposal-flatMap


适用于Chrome


该数组获取了原型.flat().flatMap() ,它们通常与lodash实现相似,但仍存在一些差异。 可选参数-设置最大树遍历深度:


 const deep_deep_array = [ '≥0 —  ', [ '≥1 —  ', [ '≥2 —  ', [ '≥3 —  ', [ '≥4 —  ' ] ] ] ] ] // 0 —     deep_deep_array.flat(0) //  ["≥0 —  ", Array(2)] // 1 —    deep_deep_array.flat() //  [" ", " ", Array(2)] deep_deep_array.flat(2) //  [" ", " ", " ", Array(2)] deep_deep_array.flat(100500) // [" ", " ", " ", " ", " "] 

.flatMap()等效于连续调用.map().flat() 。 传递给该方法的回调函数应返回一个数组,该数组将成为普通平面数组的一部分:


 ['Hello', 'World'].flatMap(word => [...word]) // ["H", "e", "l", "l", "o", "W", "o", "r", "l", "d"] 

仅使用.flat().map() ,可以将示例重写如下:


  ['Hello', 'World'].map(word => [...word]).flat() // ["H", "e", "l", "l", "o", "W", "o", "r", "l", "d"] 

另请注意,与.flat()不同, .flat()没有爬网深度设置。 因此,仅第一层将被粘合。







֍第三阶段


从草案状态中出现的提案,但尚未进入标准的最终版本。


私有\静态\公共方法\属性\类的属性


https://github.com/tc39/proposal-class-fields
https://github.com/tc39/proposal-private-methods
https://github.com/tc39/proposal-static-class-features


在某些语言中,已达成协议,要求在可见的空间中调用私有方法(“ _ ”-这样的一段,您可能会以错误的名称-下划线知道此符号)


例如,像这样:


 <?php class AdultContent { private $_age = 0; private $_content = '…is dummy example content (•)(•) —3 (.)(.) only for adults…'; function __construct($age) { $this->_age = $age; } function __get($name) { if($name === 'content') { return " (age: ".$this->_age.") → ".$this->_getContent()."\r\n"; } else { return 'without info'; } } private function _getContent() { if($this->_contentIsAllowed()) { return $this->_content; } return 'Sorry. Content not for you.'; } private function _contentIsAllowed() { return $this->_age >= 18; } function __toString() { return $this->content; } } echo "<pre>"; echo strval(new AdultContent(10)); // (age: 10) → Sorry. Content not for you echo strval(new AdultContent(25)); // (age: 25) → …is dummy example content (•)(•) —3 only for adults… $ObjectAdultContent = new AdultContent(32); echo $ObjectAdultContent->content; // (age: 32) → …is dummy example content (•)(•) —3 only for adults… ?> 

让我提醒您-这只是一个协议。 没有什么可以阻止将前缀用于其他目的,使用其他前缀或根本不使用前缀。


就个人而言,我对使用可见空间作为返回this函数的前缀的想法印象深刻。 因此,它们可以组合成一个调用链。


EcmaScript规范的开发人员走得更远,并将前缀octotorp (“ ” – 晶格 ,哈希)作为语法的一部分。


ES 10上的先前示例可以重写如下:


 export default class AdultContent { //    #age = 0 #adult_content = '…is dummy example content (•)(•) —3 (.)(.) only for adults…' constructor(age) { this.#setAge(age) } //    static #userIsAdult(age) { return age > 18 } //   get content () { return `(age: ${this.#age}) → ` + this.#allowed_content } //   get #allowed_content() { if(AdultContent.userIsAdult(this.age)){ return this.#adult_content } else { return 'Sorry. Content not for you.' } } //   #setAge(age) { this.#age = age } toString () { return this.#content } } const AdultContentForKid = new AdultContent(10) console.log(String(AdultContentForKid)) // (age: 10) → Sorry. Content not for you. console.log(AdultContentForKid.content) // (age: 10) → Sorry. Content not for you. const AdultContentForAdult = new AdultContent(25) console.log(String(AdultContentForAdult)) // (age: 25) → …is dummy example content (•)(•) —3 (.)(.) only for adults… console.log(AdultContentForAdult.content) // (age: 25) → …is dummy example content (•)(•) —3 (.)(.) only for adults… 

该示例不必要地复杂,无法一次演示私有属性,方法和属性。 但总的来说,与PHP版本相比,JS的简洁性令您大开眼界。 没有专用函数_...为您服务,在行的末尾没有分号,并且有一个点(而不是“->”)可以更深入地进入对象。


命名吸气剂。 对于动态名称,代理对象。


似乎有些琐事,但是切换到JS后,越来越少希望返回PHP。


顺便说一句,专用访问器仅在Babel 7.3.0及更高版本中可用。


在撰写本文时,npmjs.com的最新版本是7.2.2。


期待第四阶段!




舍邦文法


https://github.com/tc39/proposal-hashbang


Hashbang是Unix熟悉的为可执行文件指定解释器的一种方式:


 #!/usr/bin/env node //   'use strict'; console.log(1); 

 #!/usr/bin/env node //   export {}; console.log(1); 

Chrome SyntaxError: Invalid or&nbsp;unexpected token在类似的SyntaxError: Invalid or&nbsp;unexpected tokenSyntaxError: Invalid or&nbsp;unexpected token


BigInt大数字


https://github.com/tc39/proposal-bigint


浏览器支持

浏览器对BigInt()原语的支持


可在JavaScript中安全使用的最大整数(2⁵³-1):


 console.log(Number.MAX_SAFE_INTEGER) // 9007199254740991 

BigInt需要使用任意精度数字。


可以通过几种方式声明此类型:


 //  'n'       910000000000000100500n // 910000000000000100500n //      BigInt()   BigInt( 910000000000000200500 ) // 910000000000000200500n //     -  BigInt( "910000000000000300500" ) // 910000000000000300500n //      1642  BigInt( "" ) \\ 

这是一个新的原始类型:


 typeof 123; // → 'number' typeof 123n; // → 'bigint' 

可以与普通数字进行比较:


 42n === BigInt(42); // → true 42n == 42; // → true 

但是数学运算必须在一种类型内进行:


 20000000000000n/20n // 1000000000000n 20000000000000n/20 // Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions 

支持一元减,一元加返回错误:


  -2n // -2n +2n // Uncaught TypeError: Cannot convert a BigInt value to a number 


globalThis访问全局上下文的新方法


https://github.com/tc39/proposal-global


适用于Chrome


由于全局范围的实现取决于特定的引擎,因此您必须在执行以下操作之前:


 var getGlobal = function () { if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } throw new Error('unable to locate global object'); }; 

甚至这个选项也不能保证一切都会确定。


globalThis是所有平台访问全局范围的常用方式:


 //      globalThis.Array(1,2,3) // [1, 2, 3] //        globalThis.myGLobalSettings = { it_is_cool: true } //        globalThis.myGLobalSettings // {it_is_cool: true} 



动态import(dynamic)


https://github.com/tc39/proposal-dynamic-import


浏览器支持

浏览器对动态导入的支持


我想要导入行中的变量使用动态导入,这成为可能:


 import(`./language-packs/${navigator.language}.js`) 

动态导入是异步操作。 返回一个承诺,该承诺在加载模块后将其返回到回调函数。


因此,您可以加载模块-必要时推迟:


 element.addEventListener('click', async () => { //   await    const module = await import(`./events_scripts/supperButtonClickEvent.js`) module.clickEvent() }) 

从句法上讲,这看起来像是对import()函数的调用,但是它并不继承自Function.prototype ,这意味着它将无法通过callapply调用成功:


 import.call("example this", "argument") // Uncaught SyntaxError: Unexpected identifier 



import.meta-有关已加载模块的元信息。


https://github.com/tc39/proposal-import-meta


适用于Chrome


在已加载模块的代码中,可以获得有关它的信息。 现在,这只是模块加载的地址:


 console.log(import.meta); // { url: "file:///home/user/my-module.js" } 



JSON.stringify()方法JSON.stringify()


https://github.com/tc39/proposal-well-formed-stringify


RFC 8259的8.1节要求在封闭的生态系统之外交换的JSON文本使用UTF-8进行编码,但是JSON.stringify可以返回包含未以UTF-8表示的代码点的字符串(特别是替代代码点)从U + D800到U + DFFF)


因此,处理JSON.stringify()之后的行\uDF06\uD834变成\\udf06\\ud834


 /*         */ JSON.stringify('\uDF06\uD834') '"\\udf06\\ud834"' JSON.stringify('\uDEAD') '"\\udead"' 

事实并非如此,新规范对此进行了修复。 EdgeChrome已经更新。




不推荐使用的RegExp功能


https://github.com/tc39/proposal-regexp-legacy-features


遗留RegExp函数的规范,例如RegExp.$1RegExp.prototype.compile()方法。




原型字符串方法.trimStart().trimEnd()


https://github.com/tc39/proposal-string-left-right-trim


适用于Chrome


与方法.padStart().padEnd()类似,分别在行的开头和结尾处截断空白:


 const one = " hello and let "; const two = "us begin. "; console.log( one.trimStart() + two.trimEnd() ) // "hello and let us begin." 



.matchAll()是新的原型字符串方法。


https://github.com/tc39/proposal-string-matchall


适用于Chrome


类似于.match()方法,其g标志处于打开状态,但返回一个迭代器:


 const string_for_searh = 'olololo' //         string_for_searh.match(/o/) // ["o", index: 0, input: "olololo", groups: undefined] //       string_for_searh.match(/o/g) // ["o", "o", "o", "o"] //   string_for_searh.matchAll(/o/) // {_r: /o/g, _s: "olololo"} //        , //      .match    for(const item of string_for_searh.matchAll(/o/)) { console.log(item) } // ["o", index: 0, input: "olololo", groups: undefined] // ["o", index: 2, input: "olololo", groups: undefined] // ["o", index: 4, input: "olololo", groups: undefined] // ["o", index: 6, input: "olololo", groups: undefined] 

参数必须是正则表达式,否则将引发异常:


 'olololo'.matchAll('o') // Uncaught TypeError: o is not a regexp! 







总结


第四阶段带来了更多的外观变化。 兴趣是阶段 3Chrome中的大多数建议已经实现,并且对象的属性确实值得期待。






文章中的更正



如果您发现文章中的错误,错误或需要补充的地方,可以给我写一封个人信息 ,但是最好自己使用文章存储库https://github.com/KasperGreen/es10 。 为了做出积极的贡献,我将授予KDPV黄色磁铁奖章。


相关资料


英文材料 Ecma-262标准的当前版本


英文材料 Ecma-262标准的下一版本的草案


ECMAScript


JavaScript中新的#个私有类字段


关于哈布雷的文章 ES7,ES8和ES9标准概述


舍邦


关于哈布雷的文章 BigInt-JavaScript中的长算术


关于哈布雷的文章 JavaScript模块路径


英文材料 为什么不私人x


关于哈布雷的文章 ECMAScript建议:Array.prototype。{Flat,flatMap}


公私课领域


JavaScript:整体优势




UPD(3月):


将状态更改为Stage - 4


.trimStart().trimEnd() -原型字符串方法


.matchAll() -具有全局标志#的 .match()


带有黄色磁铁的替代KDPV,来自elfafeya.art
图片提供者:kasper.green; 黄色磁铁:elfafeya.art和kasper.green

Source: https://habr.com/ru/post/zh-CN437806/


All Articles