第91次TC39会议举行,这还是我认识的JS吗?

大家好,我是若川。持续组织了近一年的源码共读活动,感兴趣的可以 加我微信 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 的规范中分为五步:

  • stage0(strawman),任何TC39的成员都可以提交。

  • stage1(proposal),进入此阶段就意味着这一提案被认为是正式的了,需要对此提案的场景与API进行详尽的描述。

  • stage2(draft),演进到这一阶段的提案如果能最终进入到标准,那么在之后的阶段都不会有太大的变化,因为理论上只接受增量修改。

  • state3(candidate),这一阶段的提案只有在遇到了重大问题才会修改,规范文档需要被全面的完成。

  • state4(finished),这一阶段的提案将会被纳入到ES每年发布的规范之中。

1、第四阶段

(1)Hashbang Grammar

Unix 的命令行脚本都支持#!命令,又称为 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-hashbang

2、第三阶段

(1)Duplicate 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-groups

3、第二阶段

(1)Import 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-reflection

4、第一阶段

(1)Symbol 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

了解是否获得了真正独一无二的 symbol:

const 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。

两个方法的 Polyfill:

  • Symbol.isRegistered(symbol): https://github.com/inspect-js/is-registered-symbol

  • Symbol.isWellKnown(symbol): https://github.com/inspect-js/is-well-known-symbol

提案地址:https://github.com/tc39/proposal-symbol-predicates

(2)Policy 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.size:s中值的个数。

  • 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():不确定是否应该实现。

(1)FIFOMap 和 FIFOSet

new FIFOMap(maxNumOfEntries, entries = [])
new FIFOSet(maxNumOfValues, values = [])

如果给定非整数最大数量的 entries/values,或者初始 entries/values 不可迭代,则构造函数将抛出 TypeErrors。

它们的实例按照它们添加的顺序逐出 entries/values,就像 FIFO 队列一样。

(2)LIFOMap and LIFOSet

new LIFOMap(maxNumOfEntries, entries = [])
new LIFOSet(maxNumOfValues, values = [])

如果为这些构造函数提供了非整数的最大 entries/values,或者初始 entries/values 不可迭代,则这些构造函数将抛出 TypeErrors。

它们的实例按照添加顺序逐出 entries/values,就像 LIFO 堆栈一样。

(3)LRUMap and LRUSet

new LIFOMap(maxNumOfEntries, entries = [])
new LIFOSet(maxNumOfValues, values = [])

如果为这些构造函数提供了非整数的最大 entries/values 数,或者初始 entries/values 不可迭代,则这些构造函数将抛出 TypeErrors。

(4)LFUMap 和 LFUSet

new 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-set

(3)Function 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-memo

(4)Object 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 方法,就可以轻松解决上述问题。

有人认为,我们可以实现如下 pickomit

const 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+的大厂前端面试

669b82e0a35e55f20cbba9802ab39bc3.gif

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经坚持写了8年,点击查看年度总结。
同时,最近组织了源码共读活动,帮助4000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。

48237baaf48f379ea7d3c8cb53a2043b.jpeg

扫码加我微信 lxchuan12、拉你进源码共读

今日话题

目前建有江西|湖南|湖北 籍 前端群,想进群的可以加我微信 lxchuan12 进群。分享、收藏、点赞、在看我的文章就是对我最大的支持~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/274586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android调节音量——AudioManager的应用

Android中可以通过程序获取系统手机的铃声和音量。同样&#xff0c;也可以设置铃声和音量。Android中给出了AudioManager类来实现音量获取、音量控制。本篇基于 Android API 中的 AudioManager 作讲述&#xff0c;最后给出实例。下面是本篇大纲&#xff1a;1、认识 AudioManage…

静态创意和动态创意_再次发挥创意需要什么?

静态创意和动态创意重点 (Top highlight)According to Oxford dictionary, creativity means “1. Inventiveness. 2. the use of imagination or original ideas to create something.”根据牛津词典&#xff0c;创造力意味着“ 1。 创造力。 2.利用想象力或独创性的思想来创造…

我写了 ahooks 源码分析系列,收到官方邀请我一起维护,这是一次提 PR 的记录...

大家好&#xff0c;我是若川。持续组织了近一年的源码共读活动&#xff0c;感兴趣的可以 加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

Hdu 4415 Assassin's Creed 【贪心】.cpp

题意&#xff1a; 某A有一个剑 坚韧度为m 他可以用这个剑去攻打别的队伍 杀掉第 i 个队伍需要消耗的坚韧度为 Ai 并可以用得到的剑去打别的队(Bi个) 但是打完别的队这个剑就不能用了 问怎么用最少的坚韧度击败最多的队伍 给出T组样例 每个样例给出n m n表示有n个队 接下来n行给…

ahooks 整体架构篇,大家都能看得懂

大家好&#xff0c;我是若川。持续组织了近一年的源码共读活动&#xff0c;感兴趣的可以 加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

gif动态图gif出处_我喜欢GIF的怪异事物

gif动态图gif出处I was recently reminded that I never wrote down all the weird things I learned about the GIF file format when implementing GIF decoding/playback at work last year. (I was reminded of this because I wrote a line in a corporate blog post draf…

Git基础教程(必学)

大家好&#xff0c;我是若川。持续组织了近一年的源码共读活动&#xff0c;感兴趣的可以 加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

用户体验改善案例_优化用户体验案例研究的五种方法

用户体验改善案例重点 (Top highlight)I’ve had the opportunity to give several portfolio reviews, and I want to share some common themes I see and how you can improve them to put your best foot forward as you search for that new product design gig.我有机会发…

我捡到宝了!2022版前端面试上岸手册,最新最细致!

大裁员背景下&#xff0c;没什么比辞职后找不到工作更扎心&#xff01;在行情好转前&#xff0c;前端程序员只能“猥琐发育”&#xff0c;不轻易跳槽&#xff0c;同时要修炼内功&#xff1a;对八股文、底层源码、重点项目等进行查缺补漏&#xff0c;静待行情好转抓住机会&#…

flo file_Flo菜单简介:可扩展的拇指友好型移动导航

flo fileWhen it comes to using my phone, I’m a thumb guy and I like using my phone held in one hand. Well, apparently 49% of us prefer it like this.说到使用手机&#xff0c;我是个拇指小伙&#xff0c;我喜欢用一只手握住手机。 好吧&#xff0c;显然我们当中有49…

超炫的iphone应用UI/UX设计赏析

日期&#xff1a;2012-10-5 来源&#xff1a;GBin1.com 要想成为一款成功的iOS应用&#xff0c;不单单是功能设计&#xff0c;还需要有超棒的用户界面和用户体验的完美设计。为了带给大家更多的设计灵感&#xff0c;今天我们分享另外一套来自dribbble的iOS应用UI和UX设计&…

Git实战进阶教程

大家好&#xff0c;我是若川。持续组织了近一年的源码共读活动&#xff0c;感兴趣的可以 加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

什么是设计模式_什么是设计?

什么是设计模式Imagine, you are out waiting for a taxi. You are about to miss your appointment. You wait for minutes but Good Lord! — there’s not a single taxi that can offer you a ride.想象一下&#xff0c;您正在外面等出租车。 您将错过约会。 您等待几分钟&…

有哪些值得学习的大型 React 开源项目?

大家好&#xff0c;我是若川。持续组织了近一年的源码共读活动&#xff0c;感兴趣的可以 加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

成年人的样子是什么样子_不只是看样子

成年人的样子是什么样子As a branding, packaging, and digital product designer, both at Input Logic and as a freelancer, I work with clients across a wide array of industries, and am responsible for simultaneously getting to the heart of what each client wan…

如何在工作中打造影响力,带动同事?

大家好&#xff0c;我是若川。持续组织了近一年的源码共读活动&#xff0c;感兴趣的可以 加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

谷歌maps菜单语言设置_Google Maps:拯救未来之路— UX案例研究

谷歌maps菜单语言设置I have a lousy sense of direction, so Google Maps has always been my right-hand app. On a whim last year, I decided to skip the beach and sunburn and head to Budapest for spring break. That’s when Google Maps became my best friend.我的…

1万小时后,我从外包走进了字节跳动,现在出了一本书,文末送书!

谨以此书献给相信“努力有用”的你by 大史不说话《 前端跨界开发指南&#xff1a;JavaScript工具库原理解析与实战》先做个自我介绍我是大史不说话&#xff0c;是一名前端工程师&#xff0c;一个相信“努力有用”的、不太聪明的、行动力还可以的程序员。曾经因为一篇《10000小时…

视觉设计师跟平面设计_使设计具有视觉吸引力

视觉设计师跟平面设计Interaction Design is very gratifying.交互设计非常令人满意。 From fast critical thinking to extracting ideas in tangible forms within the team is sure fun and challenging.从快速的批判性思维到在团队内部以有形的形式提炼想法&#xff0c;无…

ExtJs4 笔记 Ext.tab.Panel 选项卡

本篇讲解选项卡控件。 一、基本选项卡 首先我们来定义一个基本的选项卡控件&#xff0c;其中每个Tab各有不同&#xff0c;Tab的正文内容可以有三种方式获取&#xff1a; 1.基本方式:通过定义html和items的方式。 2.读取其他html的信息:通过设置contentEl就可以获取其他html的信…