3

下面的代码片段是我们npm run devsvelte应用程序上执行时生成的。

    function make_dirty(component, i) {
        if (component.$$.dirty[0] === -1) {
            dirty_components.push(component);
            schedule_update();
            component.$$.dirty.fill(0);
        }
        component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
    }

任何人都可以解释下面的声明发生了什么吗?为什么数字 31 是硬编码的?

component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31)); 

谢谢

4

2 回答 2

5

为了扩展 Tijmen 的答案,我将尝试解释此代码的一些基本原理以及它实际在做什么。

位掩码是一种将多个布尔选项存储在单个整数中的技术。假设您有选项 A、B、C 和 D——您将值 1、2、4 和 8 分配给它们,然后您可以存储这些选项的任意组合,如下所示:

  • AB — 3
  • BD — 10
  • ACD — 13

稍后,您可以使用按位运算符检索该值:

if (opts & 1) console.log('A was selected');
if (opts & 2) console.log('B was selected');
if (opts & 4) console.log('C was selected');
if (opts & 8) console.log('D was selected');

Svelte 使用位掩码来跟踪哪些值是的,即自上次更新组件以来发生了什么变化。由于 Tijmen 描述的 31 位限制,单个位掩码只能让我们在一个组件中拥有 31 个变量——在大多数情况下很多,但肯定不是全部。component.$$.dirty位掩码数组也是如此。

这行代码...

component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));

...弄脏正确位掩码的正确位 -(i / 31) | 0为我们提供位掩码的索引,(1 << (i % 31))为我们提供该位掩码内的位值,并将|=该位设置为 1,无论其之前的值是什么。

-1 用作标记,用于指示组件之前根本没有脏,以便 Svelte 可以将其添加到需要在下一次更新中更新的组件列表中。

于 2020-01-01T23:43:29.870 回答
2

脏数组是一个以整数形式存储多个布尔变量的数组,也称为位数组

默认情况下,JavaScript 中的整数是有符号的和 32 位的。它每个整数只存储 31 位而不是 32 位的原因是因为它是有符号的,如果设置了最后一位,则使整数表示负数。我缺少一些上下文,但是查看第一个 if 语句,代码似乎为特殊情况保留了负数。

于 2019-12-31T16:40:31.540 回答