有时,区块码生成器需要引用其内部代码的 进行多次屏蔽
例如,如果有用于输出列表最后一个元素的块, 需要多次访问列表代码:
// 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`;
}