周刊第7期:使用新的周刊模板

使用新的周刊模板

在本期开始采用新的周刊模板,新增了两个模块:

  • 本周见闻:一些有趣的事情、观点,与「分享文章」最大的区别在于它们通常是一些比较简短的信息。
  • tips:一些有用的技巧,可以帮助你提高工作效率。

如此,周刊内容就显得更加丰富,可以分享更多元的信息了。

本周见闻

React v18 正式发布

  1. 自动批处理

    批处理是指 React 将多个状态更新合并到单个 re-render 中以获得更好的性能。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 在之前: 只有 React 事件是批处理的。
    setTimeout(() => {
    setCount(c => c + 1);
    setFlag(f => !f);
    // React 将渲染两次,每次状态更新一次(没有批处理的情况)
    }, 1000);

    // 在之后: setTimeout、Promise、原生事件这类异步操作都将合并到一次 re-render 中。
    setTimeout(() => {
    setCount(c => c + 1);
    setFlag(f => !f);
    // React 只会在最后重新渲染一次(这就是批处理!)
    }, 1000);

    了解更多:https://github.com/reactwg/react-18/discussions/21

  2. Transitions

    这是 React 中的一个新概念,用于区分紧急和非紧急更新(过渡更新)。

    • 紧急更新:反映了直接交互,如输入、单击、按下等。
    • 过渡更新:将 UI 从一个视图转换为另一个视图。

    通常,为了获得最佳用户体验,单个用户输入应同时导致紧急更新和非紧急更新。您可以在输入事件中使用 startTransition API 来通知 React 哪些更新是紧急的,哪些是过渡的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import {startTransition} from 'react';

    // 紧急,显示输入的内容
    setInputValue(input);

    // 将内部的任何状态更新标记为转换
    startTransition(() => {
    // 过渡:显示结果
    setSearchQuery(input);
    });

    startTransition 中包含的更新操作都将作为过渡更新进行处理,如果出现更紧急的更新,则会打断之前的过渡更新,只渲染最新的。

    了解更多:https://reactjs.org/docs/react-api.html#transitions

  1. Hooks

    1. useId:用于在客户端和服务器上生成唯一 ID
    2. useTransition:标记为过渡性更新。
    3. useDeferredValue:允许您延迟重新渲染树的非紧急部分,类似于防抖。
    4. useSyncExternalStore:允许外部存储通过强制对存储的更新为同步来支持并发读取。
    5. useInsertionEffect:允许 CSS-in-JS 库解决在渲染中注入样式的性能问题。

关于 React v18 更多新功能请查看:React v18.0 – React Blog

CSS 新提案 - 共享元素转场效果

CSS 的一个新提案,为切换页面提供平滑加载动画,无论是 SPA 还是 MPA 都适用,效果如下:

关于更多可了解:shared-element-transitions/explainer.md

尊重用户的默认字体大小

在处理文本和 CSS 时,我们通常都会默认设置一个固定的字体大小:

1
2
3
html {
font-size: 16px;
}

这在大部分 WEB 网站都没有问题,但是对于内容网站(如新闻网站、论坛、博客等),这可能会导致可用性问题,因为每个人设置的默认字体大小有可能不一样,比如在 Chrome 就可以通过 chrome://settings/fonts 更改字体大小,所以更好的做法是:

1
2
3
html {
font-size: 100%;
}

然后在内部元素采用 emrem

TypeScript 的 Web API 类型声明是怎么来的?

在 TypeScript 中,所有的 Web API 类型声明都在 lib.dom.d.ts 中实现,一共多达 18877 行,它当然不是手动编写的,而是利用 webref 进行生成机器可读的 Web 标准,每 6 小时自动生成一次,然后利用 TypeScript-DOM-lib-generator 自动生成 lib.dom.d.ts。

一些 tips

使用 Lighthouse 展示网站的 JavaScript 依赖关系

熟悉 Webpack 的前端同学应该知道有一个插件叫做 Webpack-bundle-analyzer,它用于展示每个 npm 包的体积。

现在我们也可以通过 Lighthouse Treemap 查看网站的 JavaScript 依赖关系和文件体积,效果如下:

使用方法:在 Chrome 使用 Lighthouse 检查,然后在结果页中点击「View Treemap」即可。

分享文章

我讨厌的5个编码面试问题

本文列举几个作者最不喜欢的五类面试题目:

  1. 一些不重要的琐事

    这一类面试题通常是一些实际工作中很少遇到的场景,比如:

    1
    2
    3
    4
    5
    const x = {};
    const y = {};
    x.__proto__ = y;
    y.__proto__ = x;
    console.log(x.field);

    首先 __proto__ 并不是一个标准的属性,实际工作中也应该避免使用它来修改原型链,能够正确回答它并不能真正显示候选人的 JavaScript 水平,只能体现他看过多少面试题。

    这些题目通常关注于一些 JavaScript ES5 之前的糟粕,但现在已经是 2022 年了,我们没有必要再问这类问题。

  2. 具体的细节

    这类问题通常过于关注细节,比如:

    • 迁移到 Webpack 6 会遇到什么问题?
    • 如何检查浏览器对服务器发送事件的支持?

    这些问题,即便候选人真的在工作中解决过,除非事先准备好,否则也很难完整地回答出来,但我们都擅长通过搜索引擎解决这类问题。

    这些题目极有可能是面试官最近解决过的一些棘手问题,他对此记忆犹新,但是根据这些问题来判断候选人的能力是不公平的,因为即便候选人回答不出来,也不代表他无法解决此类问题,这只是双方信息不对称所导致的。

    所以面试官更应该着重关注于候选人最近解决过什么棘手问题,以此判断候选人解决问题的能力。

  3. 混淆问题

    这些问题通常具有一个标准的答案,比如:

    1. Number 和 Object 之间有什么区别?

    这个题目的答案仅仅是:Number 是不可变的。

    但候选人可能会认为这是一个开放式的题目,因此会从各方面对它们进行对比,这严重浪费时间。

    同样的,这些问题也体现出候选人的面试经验,只有他被问过几次同样的题目,才熟练地知道它具有一个标准的答案。

    所以面试官应该更直接地问:哪些 JavaScript 类型是不可变的。

  4. 实现问题

    这类问题通常与浏览器实现细节相关,但它们不在规范里面:

    • console.log(Object.keys({ x: 0, y: 0 }).join()) 问 x 和 y 哪个在前面?

    大多数人都知道正确的答案:根据添加顺序进行排序。

    但此类特性依赖于 JS 引擎的实现,在 ECMAScript 规范中并没有明确定义。

    所以面试官在问这类题目的时候,不应该持有标准化答案的心态,它更应该是一个开放式的题目。

    PS:笔者曾写过一篇文章深入剖析 Object.keys 的规范:《一行 Object.keys() 引发的血案》。

  5. 缺少上下文

    开放式问题是你在面试中可以问的最好的问题之一,因为它们具有挑战性,并能够真正体现候选人解决问题的能力,然而这些问题取决于面试官个人观点,否则容易引起反作用。

    例如,这个函数有什么问题:

    1
    2
    3
    4
    5
    6
    function map(arr, fn) {
    for (var i = 0; i < arr.length; i++) {
    arr[i] = fn(arr[i]);
    }
    return arr;
    }

    这个问题对于不同的人具有不同的观点,有些人觉得这段代码问题一大堆,比如:

    1. 为什么使用 var 而不是 let
    2. 为什么不使用 for...of ?
    3. 它具有副作用,不应该直接修改 arr
    4. 为什么不直接使用 .map() ?

    但也有人觉得它没有任何问题,既然它能够正常工作,我们为什么需要重构它?仅仅是为了让它看上去更好吗?我们的目标是什么?没有明确目标的重构就是浪费时间!

    所以,双方都没有错,因为它完全取决于上下文。

    所以,当你提出一个开放式问题时,要么放下你预期的答案,专注于解决问题的过程,要么引入缺失的要求来指导你想要的解决方案。

    最后,作者给出了一个如何改进面试题目的建议:

    img

不良面试官的七个习惯

此文接着上一篇《我讨厌的5个编码面试问题》,列举几个面试官不好的习惯:

  1. 骄傲的自负

    有些面试官通常抱有一种「既然是我在面试你,那么我的能力自然比你强」的心态,他们往往摆出一副居高临下的样子,但你要清楚,你掌握所有面试问题的答案,这本就是一种信息不对称,所以你不应该抱有这种想法。

  2. 专注于答案

    就像考试一样,面试官列出所有的面试题目,照本宣科地问问题,这类问题通常具有标准答案,但真正的工作中很少是考试一样解决问题的,并且这类问题都可以通过搜索引擎解决。

    我们更应该倾向于开放式的题目,专注于候选人解决问题的过程,比如问「如何设计一个 Swiper」会比「具有哪些触摸事件」更合适。

    此类问题其实还蕴含了一个顾虑:不信任候选人,认为他们缺乏这些基础知识。

  3. 不给出任何提示

    试问当你身边的同事在某个问题卡住的时候,你会选择帮助他还是立即解雇他?所以我们应该引导候选人,而不是让他一个人苦苦挣扎。

  4. 规划不善

    面试前没有提前规划好面试流程、或者是面试流程安排得太紧凑都会导致面试效果不佳。

    假设你们明显有可能在某个问题上进行深入地探讨,千万不要仅仅因为你需要问更多初级的问题而打断候选人展示自己的机会。又或者你招聘的是高级开发人员,而候选者碰巧是一位非常不错的初级开发人员,你也不要轻易地错过。

  5. 忽略简历

    不要浪费候选人的宝贵时间,假设候选人是一位顶尖大学毕业、甚至有一个技术博客和开源项目,这都可以体现出候选人的专业技能,而面试官仍要花费近 30 分钟去问一些基础问题,这会让候选人觉得是在浪费自己的时间。

    诚然简历是可以造假,但仍不应该花费过多的时间去印证候选人是否具备这些基础知识,把时间花在更有价值的问题上。

  6. 过渡延长

    不要让面试时间过长,除非你有自信保证候选人愿意花费这么多时间。

  7. 避免群体面试的不良反应

    多个面试官时千万不要你一句我一句的,也不要显得某个面试官在场是完全没必要的,更好的做法是其中一位面试官负责主要的问题,其他面试官负责观察。

如何看待 ECMAScript 新提案 - Type Annotations

这个月有一个 ECMAScript 的新提案,可以在 JavaScript 中使用 TypeScript 部分类型声明,参见:tc39/proposal-type-annotations

此提案一经提出,在中英文社区都引起了不少的轰动,而《JavaScript for impatient programmers》的作者 Dr. Axel Rauschmayer 在这篇文章中提出了一些他的看法。

先展示一下这个提案的一些使用示例:

1
2
3
function add(x: number, y: number) {
return x + y;
}

很标准的 TypeScript 语法,而 JavaScript 将这样处理这些类型声明:

  1. 在运行时,JavaScript 引擎完全忽略它们 - 就好像它们是注释一样。
  2. 在开发时,类型检查器可以静态分析注释并警告开发人员有关潜在问题。

下面是本文作者的一些看法:

  • 优点:
    • 为类型声明标准化是很好的,并且将使该领域的工具和实验更容易。
    • 可以在不编译源代码的情况下使用 TypeScript 进行编程(例如)。在开发时只会进行类型检查。这将大大改善静态类型 JavaScript 的开发体验:
      • 执行时不需要中间文件。
        • 这在 Node 上特别有用 .js 您可以直接运行 TypeScript 文件。
      • 调试时,不需要源映射即可查看原始源代码。
      • .d.ts文件通常也不需要。
  • 缺点:
    • 像 TypeScript 这样的静态类型系统是完全可选的 JavaScript 之上的层,不会给 JavaScript 增加任何复杂性。
    • 该提案为该语言添加了许多新的语法。即使引擎忽略它,它们仍然必须能够解析它。升级 JavaScript 工具需要时间和精力。
    • 如果在将库部署到 npm 之前没有将 TypeScript(等)编译为 JavaScript,那么对于不喜欢 TypeScript 的人来说,浏览 TypeScript 开发人员编写的源代码将变得不那么愉快。
      • 为了帮助解决这个问题,从文件中删除所有类型批注可能成为文本编辑器支持的操作。

个人思考

我个人非常喜欢这个提案,也很希望这个提案能够最终进入到 ECMAScript 的标准中。但这背后仍会有无数的坑,比如 add<number>(4,5) 它也是合法的 JavaScript 代码,至于如何解决这类与现有代码冲突的问题,就让我们拭目以待吧。

有趣的链接

  • Git 飞行规则(Flight Rules):这是一篇给宇航员(这里就是指使用 Git 的程序员们)的指南,用来指导问题出现后的应对之法。

  • 里科的备忘单:一些语言、框架、工具的 TL;DR,帮助你快速了解某一门技术。

  • 访问指南:这是对可访问性的友好介绍!列出了很多有用的知识帮助你提高网站的可访问性。

作者 : 4Ark
来源 : https://4ark.me
著作权归作者所有,转载请联系作者获得授权。

🥳 加载 Disqus 评论