广州网站建设公司哪家服务好,南通高端网站,wordpress彩带背景,企业网站改一下多少钱大家好#xff0c;我是若川。持续组织了近一年的源码共读活动#xff0c;感兴趣的可以 加我微信 ruochuan12 参与#xff0c;每周大家一起学习200行左右的源码#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外… 大家好我是若川。持续组织了近一年的源码共读活动感兴趣的可以 加我微信 ruochuan12 参与每周大家一起学习200行左右的源码共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外目前建有江西|湖南|湖北籍前端群可加我微信进群。2022 年 7 月 19 日至 21 日由 Google 主办的 TC39 第 91 次会议在美国旧金山举行。以下 ECMAscript 提案在该会议上取得了阶段性进展☀️ 第四阶段Hashbang Grammar允许 JavaScript 文件头使用 #! 用于 shell 识别解释器。 第三阶段Duplicate named capturing groups允许正则表达式捕获组的命名重复。 第二阶段Import Reflection建议使用导入反射属性导入 ES 模块的语法。 第一阶段Symbol Predicates建议引入区分 symbol 的方法。Policy Maps and Sets具有缓存替换策略如 LRU 和 LFU的 Maps 和 Sets 提案。Function Memoization函数记忆。Object pick/omit符合人体工程学的动态对象重构。TC39 是专门负责定义 JavaScript 标准的技术委员会根据 ECMAScript 规范对 JavaScript 语言进行了标准化包括但不限于语言的语法、语义、库和支持该语言的补充技术。 对于新提案从提出到最后被纳入 ECMAScript 新特性TC39 的规范中分为五步stage0strawman任何TC39的成员都可以提交。stage1proposal进入此阶段就意味着这一提案被认为是正式的了需要对此提案的场景与API进行详尽的描述。stage2draft演进到这一阶段的提案如果能最终进入到标准那么在之后的阶段都不会有太大的变化因为理论上只接受增量修改。state3candidate这一阶段的提案只有在遇到了重大问题才会修改规范文档需要被全面的完成。state4finished这一阶段的提案将会被纳入到ES每年发布的规范之中。1、第四阶段 1Hashbang GrammarUnix 的命令行脚本都支持#!命令又称为 Hashbang。这个命令放在脚本的第一行用来指定脚本的执行器。Hashbang Grammar 提案就是想为JavaScript 脚本引入了#!命令这个命令写在脚本文件或者模块文件的第一行// 写在脚本文件的第一行
#!/usr/bin/env node
use strict;
console.log(1);// 写在模块文件的第一行
#!/usr/bin/env node
export {};
console.log(1);这样Unix 命令行就可以直接执行脚本了# 以前执行脚本
node hello.js# 有了 hashbang 之后执行脚本
./hello.js不过这样的话hashbang 就必须严格的在文件头否则就会出现语法错误导致这个JavaScript脚本文件无法使用。提案地址https://github.com/tc39/proposal-hashbang2、第三阶段 1Duplicate named capturing groups在正则表达式中可以使用捕获组来对匹配模式中的某一部分做独立匹配。现在在 JavaScript 中正则表达式中的命名捕获组需要是唯一的。const str 2022-07;
const reg /(?year[0-9]{4})-(?month[0-9]{2})/;const group str.match(reg).groups;group.year; // 2022对于以下正则表达式即匹配“2022-07”格式和“07-2022”格式/(?year[0-9]{4})-[0-9]{2}|[0-9]{2}-(?year[0-9]{4})/这是一个错误因为重复使用了名称year。但有时想匹配一个可以用多种格式编写的东西如上。能够在这种情况下使用相同的命名会很好。Duplicate named capturing groups 提案就是为解决这个问题。此提案提出允许捕获组的命名可以重复以此来支持上面这种场景。此提案允许在名称出现在不同|时重用它们。提案地址https://github.com/tc39/proposal-duplicate-named-capturing-groups3、第二阶段 1Import Reflection对于 JavaScript 和 WebAssembly需要能够在标准主机执行模型之外更紧密地自定义模块的加载、链接和执行。对于 JavaScript创建 userland loaders 需要模块反射类型以便共享主机解析、执行、安全和缓存语义。在语法上支持模块反射作为一种新的导入形式创建了一个原语可以将模块的静态、安全和工具优势从 ESM 集成扩展到这些动态实例化用例中。import module x from specifier;module 反射类型被添加到 ImportStatement 的开头。仅支持上述形式不支持命名导出和未绑定声明。动态导入const x await import(specifier, { reflect: module });对于动态导入模块导入反射在指定导入断言的第二个属性选项包中使用 reflect 指定。提案地址https://github.com/tc39/proposal-import-reflection4、第一阶段 1Symbol Predicates该提案提出了两个区分 symbol 的方法Symbol.isRegistered(symbol)Symbol.isWellKnown(symbol)在实际使用时并非所有 symbol 都是相同的并且更多地了解它们的含义可能很有用尤其是对于库而言。了解 symbol 是否真正独一无二、可伪造、跨领域共享可能很重要具体还是要器具与其用例。可以在库中检测 symbol 是否可以用作 WeakMap 键function isWeakMapKey(key) {switch (typeof key): {case object:return key ! null;case function:return true;case symbol:return !Symbol.isRegistered(sym);}return false;
}isWeakMapKey({}); // true
isWeakMapKey(Symbol()); // true
isWeakMapKey(foo); // false
isWeakMapKey(Symbol.for(foo)); // false
isWeakMapKey(Symbol.asyncIterator); // true了解是否获得了真正独一无二的 symbolconst isUniqueSymbol sym typeof sym symbol !(Symbol.isRegistered(sym) || Symbol.isWellKnown(sym));isUniqueSymbol(Symbol()); // true
isUniqueSymbol(Symbol.for(foo)); // false
isUniqueSymbol(Symbol.asyncIterator); // false
isUniqueSymbol({}); // false提案中的两个方法Symbol.isRegistered(value)将未知值作为唯一参数返回布尔值如果 symbol 已注册则返回 true否则返回 false。Symbol.isWellKnown(value)将未知值作为唯一参数返回布尔值如果 symbol 是 ECMA262 和 ECMA402 定义的已知的 symbol 之一则返回 true否则返回 false。两个方法的 PolyfillSymbol.isRegistered(symbol): https://github.com/inspect-js/is-registered-symbolSymbol.isWellKnown(symbol): https://github.com/inspect-js/is-well-known-symbol提案地址https://github.com/tc39/proposal-symbol-predicates2Policy Maps and Sets开发人员经常使用 Map 数据结构作为缓存并且有时希望限制缓存的内存消耗。建议探索向 JavaScript 语言添加映射数据结构以支持各种基本的简单缓存替换策略例如 LRU最近最少使用、LFU最不常用、FIFO先进先出和 LIFO 后进先出。该提案将向全局对象添加几个内置类。它们中的每一个都有一个可变的类似 Map 的接口或一个可变的类似 Set 的接口。对于类似 Map 的类这些包括m.size: m 中的值的数量。m.has(key): 返回一个布尔值m 是否具有给定 key。m.get(key)查找指定的 key如果有则返回 m 中该 key 对应的的 value否则返回undefined。m.set(key, value)将 m 中key 的值设置为 value返回m自身。m.delete(key)删除指定 key 及对应的 value如果有。返回一个布尔值表示在删除之前 m 中是否有该 key。m.clear()从 m 中删除所有内容。返回 undefined。m[Symbol.iterator](): 不确定是否应该实现。m.entries(): 不确定是否应该实现。m.keys(): 不确定是否应该实现。m.values(): 不确定是否应该实现。m.forEach(): 不确定是否应该实现。对于类似 Set 的类这些包括s.sizes中值的个数。s.has(value)返回 s 是否具有给定 value 的布尔值。s.add(value)将给定值添加到 s返回 s 本身。s.delete(key)如果 s 有值则从 s 中删除给定值。返回在删除值之前 s 是否具有值的布尔值。s.clear()从 s 中删除所有值返回 undefined。m[Symbol.iterator]()不确定是否应该实现。s.values()不确定是否应该实现。s.forEach()不确定是否应该实现。1FIFOMap 和 FIFOSetnew FIFOMap(maxNumOfEntries, entries [])
new FIFOSet(maxNumOfValues, values [])如果给定非整数最大数量的 entries/values或者初始 entries/values 不可迭代则构造函数将抛出 TypeErrors。它们的实例按照它们添加的顺序逐出 entries/values就像 FIFO 队列一样。2LIFOMap and LIFOSetnew LIFOMap(maxNumOfEntries, entries [])
new LIFOSet(maxNumOfValues, values [])如果为这些构造函数提供了非整数的最大 entries/values或者初始 entries/values 不可迭代则这些构造函数将抛出 TypeErrors。它们的实例按照添加顺序逐出 entries/values就像 LIFO 堆栈一样。3LRUMap and LRUSetnew LIFOMap(maxNumOfEntries, entries [])
new LIFOSet(maxNumOfValues, values [])如果为这些构造函数提供了非整数的最大 entries/values 数或者初始 entries/values 不可迭代则这些构造函数将抛出 TypeErrors。4LFUMap 和 LFUSetnew LIFOMap(maxNumOfEntries, entries [])
new LIFOSet(maxNumOfValues, values [])如果为这些构造函数提供了非整数的最大 entries/values 数或者初始 entries/values 不可迭代则这些构造函数将抛出 TypeErrors。替代解决方案可以向现有的 Map 和 Set 构造函数添加可选参数const cache new Map(initialEntries, 256, policyType);提案地址https://github.com/tc39/proposal-policy-map-set3Function Memoization函数记忆是一种常用的技术它会缓存函数调用的结果并在再次出现相同的输入时返回缓存的结果。这些对以下情况会有用在时空权衡中优化昂贵的函数调用例如阶乘、斐波那契数缓存状态→UI 计算例如在 React 的 useMemo 中确保回调始终返回相同的单例对象逻辑编程中的表格函数记忆时很有用的。建议探索在 JavaScript 语言中添加一个 memoization API。Function.prototype.memo 方法将创建一个新函数该函数对给定参数的每个元组最多调用一次原始函数。对具有相同参数的新函数的任何后续调用都将返回具有这些参数的第一次调用的结果。function f (x) { console.log(x); return x * 2; }const fMemo f.memo();
fMemo(3); // 打印 3返回 6
fMemo(3); // 不打印 返回 6
fMemo(2); // 打印 2返回 4
fMemo(2); // 不打印 返回 4
fMemo(3); // 不打印 返回 6此外还可以添加一个函数装饰器版本Function.memo。这将更容易将 memoization 应用于函数声明Function.memo
function f (x) { console.log(x); return x * 2; }两个版本都可以使用递归函数// 原型方法版本
const getFibonacci (function (n) {if (n 2) {return n;} else {return getFibonacci(n - 1) getFibonacci(n - 2);}
}).memo();
console.log(getFibonacci(100));// 函数装饰器版本
Function.memo
function getFibonacci (n) {if (n 2) {return n;} else {return getFibonacci(n - 1) getFibonacci(n - 2);}
}
console.log(getFibonacci(100));结果缓存的实现开发人员将能够传递一个可选的 cache 参数此参数必须是具有 .has、.get 和 .set 方法的类 Map 对象。1元组 keys我们可以使用元组作为缓存的 key。每个元组代表对记忆函数的函数调用元组的格式为#[thisVal, newTargetVal, ...args]。对象值将替换为唯一标识该对象的 symbol。元组不能直接包含对象。memoized 函数的闭包将关闭一个内部 WeakMap该 WeakMap 将对象映射到它们的 symbol。const cache new LRUMap(256);
const f (function f (arg0) { return this.x arg0; }).memo(cache);
const o0 { x: a }, o1 { x: b };
f.call(o0, 0); // 返回 a0
f.call(o1, 1); // 返回 b1现在缓存是 LRUMap(2) { #[s0, undefined, 0] ⇒ a0, #[s1, undefined, 1] ⇒ b1 }其中 s0 和 s1 是唯一的 symbol。f 的闭包会在内部关闭 WeakMap { o0 ⇒ s0, o1 ⇒ s1 }。memo 的默认行为即不提供缓存参数是不确定的。它可能只是一个无界的普通 Map。WeakMaps 不能包含元组作为它们的 key。2组合 key?缓存 key 的另一种选择是组合 key。每个组合 key 代表对记忆函数的函数调用组合 key 的形式为 CompositeKey(thisVal, newTargetVal, ...args)。const cache new LRUMap(256);
const f (function f (arg0) { return this.x arg0; }).memo(cache);
const o0 { x: a }, o1 { x: b };
f.call(o0, 0); // 返回 a0
f.call(o1, 1); // 返回 b1现在缓存是 LRUMap(2) { compositeKey(o0, undefined, 0) ⇒ a0, compositeKey(o1, undefined, 1) ⇒ b1 }。memo 的默认行为即不提供缓存参数是不确定的。它可能只是一个 WeakMap它能够包含组合 key 作为它们的 key。提案地址https://github.com/tc39/proposal-function-memo4Object pick/omit该提案旨在实现 Object.pickObject.omit 方法类似于 TypeScript 中的 Pick 和 Omit 工具函数。先来看看这两个方法试图解决什么问题在 MouseEvent 上只需要 ctrlKey、shiftKey、altKey、metaKey 事件有一个 configObject只需要它的 [dependencies, devDependencies, peerDependencies]从 req.body 中提取 [name, company, email, password]有一个 depsObject需要忽略其中的所有 internal/packages需要通过从 ({ ...state.models, ...action.update }) 中删除 action.deleted 来构造一个 newModelData从这些例子中可以看出来对于一个对象很多时候我们只想要其中的一部分属性或者不想要其中的一些属性。如果 JavaScript 对象提供了 Object.pickObject.omit 方法就可以轻松解决上述问题。有人认为我们可以实现如下 pick 和 omitconst pick (obj, keys) Object.fromEntries(keys.map(k obj.hasOwnProperty(k) [k, obj[k]]).filter(x x)
);const omit (obj, keys) Object.fromEntries(keys.map(k !obj.hasOwnProperty(k) [k, obj[k]]).filter(x x)
);这样的实现存在以下问题不符合人体工程学如果选择解构的方式它不适用于 pick或者对于动态值的省略解构不能克隆新对象而 Object.pick 可以解构不能从原型中获取属性而 Object.pick 可以解构不能动态选择属性而 Object.pick 可以解构不能省略一些属性没有这个提议我们只能克隆和删除。语法Object.pick(obj[, pickedKeys | predictedFunction(currentValue[, key[, object]])[, thisArg])
Object.omit(obj[, omittedKeys | predictedFunction(currentValue[, key[, object]])[, thisArg])使用方式// default
Object.pick({a : 1}); // {}
Object.omit({a : 1}); // {a: 1}
Object.pick({a : 0, b : 1}, v v); // {b: 1}
Object.pick({a : 0, b : 1}, v !v); // {a: 0}
Object.pick({}, function () { console.log(this) }); // 对象本身
Object.pick({}, function () { console.log(this) }, window); // WindowObject.pick({a : 1, b : 2}, [a]); // {a: 1}
Object.omit({a : 1, b : 2}, [b]); // {a: 1}Object.pick({a : 1, b : 2}, [c]); // {}
Object.omit({a : 1, b : 2}, [c]); // {a: 1, b: 2}Object.pick([], [Symbol.iterator]); // {Symbol(Symbol.iterator): f}
Object.pick([], [length]); // {length: 0}Object.pick({a : 1, b : 2}, v v 1); // {a: 1}
Object.pick({a : 1, b : 2}, v v ! 2); // {a: 1}
Object.pick({a : 1, b : 2}, (v, k) k a); // {a: 1}
Object.pick({a : 1, b : 2}, (v, k) k ! b); // {a: 1}提案地址https://github.com/tc39/proposal-object-pick-or-omit我在阿里招前端我该怎么帮你现在还可以加模拟面试群如何拿下阿里巴巴 P6 的前端 Offer如何准备阿里P6/P7前端面试--项目经历准备篇大厂面试官常问的亮点该如何做出如何从初级到专家(P4-P7)打破成长瓶颈和有效突破若川知乎问答2年前端经验做的项目没什么技术含量怎么办如何准备20K的大厂前端面试················· 若川简介 ·················你好我是若川毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇在知乎、掘金收获超百万阅读。从2014年起每年都会写一篇年度总结已经坚持写了8年点击查看年度总结。同时最近组织了源码共读活动帮助4000前端人学会看源码。公众号愿景帮助5年内前端人走向前列。扫码加我微信 lxchuan12、拉你进源码共读群今日话题目前建有江西|湖南|湖北 籍 前端群想进群的可以加我微信 lxchuan12 进群。分享、收藏、点赞、在看我的文章就是对我最大的支持~