值块参数缓存

有时,区块码生成器需要引用其内部代码的 进行多次屏蔽

例如,如果您有一个用于获取列表最后一个元素的块,则需要 来多次访问列表代码:

// Incorrect block-code generator.
javascriptGenerator.forBlock['last_element'] = function(block, generator) {
  const listCode = generator.valueToCode(block, 'LIST', Order.MEMBER);

  // listCode gets referenced twice.
  const code = `${listCode}[${listCode}.length - 1]`;

  return [code, Order.MEMBER];
}

但是,如果内部代码块代码的结果值是 或存在副作用。例如,如果内部代码实际上是 函数调用,此特定代码最终可能会出现超出范围的情况:

randomList()[randomList().length - 1]

通过使用实用函数,您可以确保内部代码块的代码只是 只评估一次。

实用函数

实用函数是开发者定义的函数,包含在 生成的代码字符串您可以使用它们来确保内部代码块代码 只评估一次,就可以多次引用该值。

import {javascriptGenerator, Order} from 'blockly/javascript';

// Correct block-code generator.
javascriptGenerator.forBlock['last_element'] = function(block, generator) {
  const listCode = generator.valueToCode(block, 'LIST', Order.NONE);
  const functionName = generator.provideFunction_(
      'list_lastElement',
      [
        `function ${generator.FUNCTION_NAME_PLACEHOLDER_}(list) {`,
        `  return list[list.length - 1];`,
        `}`
      ]
  );

  // listCode only gets evaluated once.
  const code = `${functionName}(${listCode})`;
  return [code, Order.FUNCTION_CALL];
}

提供函数

您可以使用以下代码在块码生成器内定义实用函数: provideFunction_。它接受您想要的实用函数名称,以及 一个定义函数用途的代码字符串数组。它会返回 修改为非实用函数后(可能) 与用户定义的函数冲突。

provideFunction_ 还会对实用函数定义进行去重处理,以便每个 实用函数仅存在一次,即使定义该函数的块类型存在也是如此 。

更新优先级

定义实用函数时,还应更新优先级函数 (用于定义括号的插入方式) 块代码生成器。

优先级始终基于块码返回的代码字符串 生成器。而不关注实用函数中的运算符。因此,在 上例中的 valueToCode 调用已更改为 Order.NONE, return 元组已更改为 Order.FUNCTION_CALL