前端工具鏈沒有說的秘密

Description
随缘更新。
不妨也关注作者 GitHub:https://github.com/g-plane
Advertising
We recommend to visit

Last updated 11 months, 2 weeks ago

主要分享如何追女,怎么谈恋爱,怎么开始的问题。非黄群,不会做收费频道。

周一 - 周五 发视频教程 周六 - 周末 发电子书教程

声明:本频道主不会藏着不发做收费群。大概率是没有收费群的。所有东西都会逐步公开。

聊天群:
t.me/+F_Gq4SGhsyAxOTNh

文字版教程:https://t.me/yanzhex 全部放到这个频道了

Last updated 5 days, 2 hours ago

联系管理员: @losmyanger @dibaihaowan
狼友内部讨论群: https://t.me/+QINz1zuTRj0yMDk1
中圈频道: @modugmdjjzy 大圈频道: @mdgmddaquan 魔都群一键添加:https://t.me/addlist/yE30JrGJX8M4NDg9

Last updated 3 days ago

3 months, 1 week ago

未闭合的属性选择器,比如 a[href ,在 querySelector 中是合法的。即:

document.querySelector('a[href')

是可以的。但这种写法只针对 DOM API,在 CSS 代码里则是不合语法的。

然而,querySelector 认为 a[href= 是无效的选择器。

3 months, 3 weeks ago
7 months, 3 weeks ago

Flow 在 v0.209.0 版本(发布于 2023 年 6 月)新增一个语法支持:component syntax,这个语法专门针对编写 JSX 组件而设计。但这个语法曾在后续几个版本被临时关闭(能识别、解析语法,但会报错提示不支持),直到 v0.214.0 版本(发布于 2023 年 8 月)才重新开启。不过笔者粗略地浏览了这几个版本的更新日志,都没有看到有关 component syntax 的说明。 component syntax 大致像函数声明:通过 component 关键字(注意这只是…

Medium

New Flow Language Features for React

Write Safer and more Succinct React with Flow

Flow 在 v0.209.0 版本(发布于 2023 年 6 月)新增一个语法支持:component syntax,这个语法专门针对编写 JSX 组件而设计。但这个语法曾在后续几个版本被临时关闭(能识别、解析语法,但会报错提示不支持),直到 v0.214.0 版本(发布于 2023 年 8 月)才重新开启。不过笔者粗略地浏览了这几个版本的更新日志,都没有看到有关 component syntax 的说明。 …
8 months, 1 week ago

Flow 在 v0.209.0 版本(发布于 2023 年 6 月)新增一个语法支持:component syntax,这个语法专门针对编写 JSX 组件而设计。但这个语法曾在后续几个版本被临时关闭(能识别、解析语法,但会报错提示不支持),直到 v0.214.0 版本(发布于 2023 年 8 月)才重新开启。不过笔者粗略地浏览了这几个版本的更新日志,都没有看到有关 component syntax 的说明。

component syntax 大致像函数声明:通过 component 关键字(注意这只是 Flow 自己的「软关键字」或「上下文关键字」),随后列出参数作为组件的 props:

```
component LargeHeader(color: string) {
return


}

```

另外,从 v0.218.0 版本(发布于 2023 年 10 月)起可以像指定函数返回类型那样,指定当前组件会渲染出什么组件:

```
component LargeHeader(color: string) renders Header {
return


}

```

也是从 v0.218.0 版本起,可以指定 props 传入什么组件:

```
component Layout(header: renders Header) {
return

{header};
}

```

它还有更多的特性,例如可选参数、类型限定等,详细可阅读 Flow 文档:
1. https://flow.org/en/docs/react/component-syntax/
2. https://flow.org/en/docs/react/render-types/

11 months ago

通常的来说,我们对 V8 的认知便是性能优化极好的 JavaScript 运行引擎,但是我们可以来看一下这俩段代码。

- Object.defineProperty([], 'length', {value: \-1, configurable: true})
- Object.defineProperty([], 'len' + 'gth', {value: \-1, configurable: true})

从 JavaScript 的语义上来说,这俩段代码并没有什么不同,但是当我们将他们运行在 Chrome 或者 Node.js 中,我们便能得到俩个截然不同的错误。

`Object.defineProperty([], 'length', {value: -1, configurable: true})
VM8179:1 Uncaught RangeError: Invalid array length
at Function.defineProperty ()
at :1:8
(anonymous) @ VM8179:1

Object.defineProperty([], 'len' + 'gth', {value: -1, configurable: true})
VM8183:2 Uncaught TypeError: Cannot redefine property: length
at Function.defineProperty ()
at :2:8`

那这和 V8 性能优化极好又有什么关系呢?我们可以在他们的源码中看到如下内容:

https://github.com/v8/v8/blob/04f51bc70a38fbea743588e41290bea40830a486/src/objects/objects.cc#L3004-L3007

```
if (*name == ReadOnlyRoots(isolate).length_string()) {
// 2a. Return ArraySetLength(A, Desc).
return ArraySetLength(isolate, o, desc, should_throw);
}

```

简单理解一下,就是在这里直接使用了引用与系统内的常量字符串 "length" 引用进行了一个 O(1) 的快速匹配,从而优化了性能,但是也导致了我们上面的错误。

那么为什么 'length' 和 'len' + 'gth' 有区别呢?这个没有优化吗?我们可以在这Exploring V8's strings: implementation and optimizations》看到实际上在 V8 中存在着不同的字符串,当我们使用 %DebugPrint 对俩段内容进行输出的时候,我们可以发现:
- %DebugPrint('leng'+'th'):ONE_BYTE_STRING_TYPE- %DebugPrint('length'):ONE_BYTE_INTERNALIZED_STRING_TYPE
这也是为什么后者没办法作为一个常量字符串和全局只读常量字符串 "length" 进行比较的原因。

----
主题之外,其实我们刚刚的代码上面看到一段东西:

https://github.com/v8/v8/blob/04f51bc70a38fbea743588e41290bea40830a486/src/objects/objects.cc#L3003

```
// TODO(jkummerow): Check if we need slow string comparison.

```

#v8 #defineProperty #JavaScript

GitHub

v8/src/objects/objects.cc at 04f51bc70a38fbea743588e41290bea40830a486 · v8/v8

The official mirror of the V8 Git repository. Contribute to v8/v8 development by creating an account on GitHub.

通常的来说,我们对 V8 的认知便是性能优化极好的 JavaScript 运行引擎,但是我们可以来看一下这俩段代码。
11 months, 1 week ago

ECMAScript 有三种严格(即不会执行类型转换)相等判断的语义,分别是:
- SameValue
- SameValueZero
- IsStrictEqual

对于这三种语义,它们都会对类型不同的值返回 false;对于非数字类型的值,都会执行 SameValueNonNumber 语义;而对于数字类型,它们的差别在于比较 NaN、+0 与 -0 有不同:
- SameValue 会视 NaN 与 NaN 为相等,+0 与 -0 不等;
- SameValueZero 会视 NaN 与 NaN 为相等,+0 与 -0 相等;
- IsStrictEqual 会视 NaN 与 NaN 为不等,+0 与 -0 相等。

下面是三种语义所被使用到的常见地方:

SameValue:
- Object.is
- WeakMap 的 keyWeakSet

SameValueZero:
- Array.prototype.includes
- %TypedArray%.prototype.includes
- Map 的 keySet

IsStrictEqual:
- === 比较运算符
- Array.prototype.indexOf
- Array.prototype.lastIndexOf
- %TypedArray%.prototype.indexOf
- %TypedArray%.prototype.lastIndexOf

感谢 @JackWorks

----------------

笔者根据规律想到一个辅助记忆办法:
1. === 与 indexOf/lastIndexOf 都是 ECMAScript 中很早就存在的,对于这类「古老」的都使用 IsStrictEqual 语义;
2. includes 与 Map/Set 是 ES2015 及更晚才出现的,对于这类「新兴」的使用 SameValueZero 语义;
3. 虽然 Object.is 也是新的,但它可以被认为有别于 === 的存在,所以特殊处理(Jest 等测试框架对于 toBe 断言就是使用 Object.is 去判断);
4. WeakMap 的 key 与 WeakSet 不允许是 primitive type,因此可以忽略。

11 months, 1 week ago

位于全局的 isNaNNumber.isNaN 虽然函数名字一样,但具体行为是有差别的:
- isNaN 会对传入的参数执行类型转换,转换为数字类型后再去判断;
- Number.isNaN 则不会执行类型转换,对于数字类型以外的值均返回 false

请尽可能使用 Number.isNaN 以避免因类型转换而导致意外发生。

参考:
1. MDN 上的示例代码
2. ECMAScript 标准中关于 isNaN 的说明
3. ECMAScript 标准中关于 Number.isNaN 的说明

11 months, 1 week ago

TypeScript 新特性抢先看:新的内置类型 NoInfer<T> 。它与 Uppercase 等类型都属于 marker type(即 lib.d.ts 里的实现只有一个 intrinsic 关键字),编译器对于这类 marker type 都会特殊对待。

正如其名, NoInfer<T> 类型用于防止类型被自动推断。也就是说,在某些地方(通常是函数泛型等),如果不希望该处的类型被自动推断,就可以使用。例如:(下面的例子由官方示例简化而来)

```
declare function test(a: T, b: NoInfer): void

test('a', 'b')

```

playground
在这个例子中,参数 a 的类型将被自动推断,此时 T 为 'a' ;而对于参数 b,因为我们使用 NoInfer 类型,那么它也就不会参与自动推断,由于前面 T 被推断为 'a' ,而此处的实际参数却是 'b' ,因此类型不兼容进而报错。
如果上面没有使用 NoInfer , T 将会被推断为 'a' | 'b' ,读者可以打开 playground 链接自行修改测试。

另外, NoInfer<T> 不会对 T 产生影响,例如:

```
type Result = NoInfer<'s'>

```

playground
类型 Result 仍为 's' 。

在参与类型计算时, NoInfer<T> 其实只是被替换为 unknown 。以上面的 test 函数为例,它相当于:

```
declare function test(a: T, b: unknown): void

```

这里 T 仍为 'a' ,只不过因为使用了 unknown 而无法对参数 b 进行约束。

值得注意的是,在使用 NoInfer<T> 时,一定要留意 T 在可被推断的地方被推断为了什么类型。例如:

```
declare function test2(a: T, b: NoInfer): void

test2('a', 'b')

```

playground
它跟上面的 test 函数相比, T 没有了 extends string 的泛型约束。这时,参数 a 将被推断为 string 而不是 'a' ,也就是 T 推断为 string 。但因为 'b' 满足 string 的要求,因此这段代码不会报错。

PR: https://github.com/microsoft/TypeScript/pull/56794

11 months, 2 weeks ago

pnpm 有一个名为 resolution-mode 的配置项(在 .npmrc 文件中配置),但无论是 resolution-mode 这个名字还是配置项的值的名字,都相当的不直观,更不方便记忆。

背景:resolution-mode 影响的是 pnpm 的版本解析。适当的配置可以减少子依赖所带来的供应链攻击,并且在缓存的作用下可以加快安装速度。但请不要看到「安全」「快速」就盲目配置这个选项——阅读完下面的内容,并明确自己的意图再去动这个配置。

在解释之前,先做一些约定:
1. 不管在不同模式下,版本解析会有怎样的不同,它们都遵循语义化版本。这是大前提。
2. 下文的「子依赖」表示的是依赖的依赖,也可以被称为「间接依赖」。

目前 resolution-mode 允许设为下面三个值之一:
- highest(当前的默认值)这个模式下所有依赖(包括项目的直接依赖以及子依赖)都会被解析到最新版本;
- time-based 这个模式下项目的直接依赖会被解析到最老版本,而子依赖则会被解析到该直接依赖发布时间之前的最新版本;
- lowest-direct 这个模式下仅仅是项目的直接依赖会被解析到最老版本,子依赖会被解析到最新版本。

下面以这样的一个项目为例子:(测试时所使用的 pnpm 版本为 8.11.0)

```
{
"dependencies": {
"ora": "^6.2.0"
}
}

```

ora 库有多个依赖,但我们在这里只需要关注 ora 本身以及它的其中一个依赖 chalk 的版本,并通过 pnpm 生成的 lock file 来得知它们被解析到哪个版本。

- 当 resolution-mode 设为 highest 时:ora 的版本被解析为 6.3.1,chalk 的版本被解析为 5.3.0。两个库都被解析到最新版本。
- 当 resolution-mode 设为 time-based 时:ora 的版本被解析为 6.2.0,chalk 的版本被解析为 5.2.0。ora 能满足语义化版本的最老版本是 6.2.0,而 ora 6.2.0 的发布时间为 2023/3/19 18:13:22,在此时间之前 chalk 最新版本是 5.2.0。(尽管 ora 的 package.json 文件里声明的是 "chalk": "^5.0.0"
- 当 resolution-mode 设为 lowest-direct 时:ora 的版本被解析为 6.2.0,chalk 的版本被解析为 5.3.0。可以看到即使 ora 作为项目的直接依赖被解析为 6.2.0,但它的依赖 chalk 被解析到最新版本即 5.3.0。

参考:
1. pnpm 关于 resolution-mode 的文档
2. ora 的所有版本
3. chalk 的所有版本

11 months, 2 weeks ago
We recommend to visit

Last updated 11 months, 2 weeks ago

主要分享如何追女,怎么谈恋爱,怎么开始的问题。非黄群,不会做收费频道。

周一 - 周五 发视频教程 周六 - 周末 发电子书教程

声明:本频道主不会藏着不发做收费群。大概率是没有收费群的。所有东西都会逐步公开。

聊天群:
t.me/+F_Gq4SGhsyAxOTNh

文字版教程:https://t.me/yanzhex 全部放到这个频道了

Last updated 5 days, 2 hours ago

联系管理员: @losmyanger @dibaihaowan
狼友内部讨论群: https://t.me/+QINz1zuTRj0yMDk1
中圈频道: @modugmdjjzy 大圈频道: @mdgmddaquan 魔都群一键添加:https://t.me/addlist/yE30JrGJX8M4NDg9

Last updated 3 days ago