值块参数缓存

有时,您的块代码生成器需要多次引用其内部块的代码。

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

// 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,返回元组已更改为 Order.FUNCTION_CALL