语句会阻止缓存参数

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

例如,如果有用于输出列表最后一个元素的块, 需要多次访问列表代码:

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

  // listCode gets referenced twice.
  return `print(${listCode}[${listCode}.length - 1]);\n`;
}

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

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

通过分配给临时变量,您可以确保内部代码块的代码 只评估一次。

临时变量

临时变量用于存储内部块的代码字符串值,以便实现 代码只评估一次,然后就可以多次引用该值 次。

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

// Correct block-code generator.
javascriptGenerator.forBlock['print_last_element'] = function(block, generator) {
  const listCode = generator.valueToCode(block, 'LIST', Order.MEMBER);
  const listVar = generator.nameDB_.getDistinctName(
      'temp_list', Blockly.names.NameType.VARIABLE);

  // listCode only gets evaluated once.
  const code = `var ${listVar} = ${listCode};\n`;
  return `print(${listVar}[${listVar}.length - 1]);\n`;
}

getDistinctName 调用会接受您需要的变量名称,并返回一个 不与任何用户定义的变量冲突的名称。

减少冗余代码

使用临时变量的缺点在于,如果内部代码块的代码是一个值, 而不是函数或表达式,就会得到多余的代码:

// Assigning to temp_list is unnecessary.
var temp_list = foo;
print(temp_list[temp_list.length - 1]);

如需生成更简洁的代码,您可以检查内部块的代码是否为值,以及 则仅添加临时变量。

if (listCode.match(/^\w+$/)) {
  const code = `print(${listCode}[${listCode}.length - 1]);\n`;
} else {
  const listVar = generator.nameDB_.getDistinctName(
      'temp_list', Blockly.names.NameType.VARIABLE);
  const code = `var ${listVar} = ${listCode};\n`;
  code += `print(${listVar}[${listVar}.length - 1]);\n`;
}