La sentencia bloquea los argumentos de almacenamiento en caché

En ocasiones, el generador de código de bloque necesita hacer referencia al código de su bloque interno varias veces.

Por ejemplo, si tienes un bloque que imprime el último elemento de una lista, debes acceder al código de la lista varias veces:

// 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`;
}

Sin embargo, esto puede causar problemas si el valor resultante del código del bloque interno no es coherente o si tiene efectos secundarios. Por ejemplo, si el código interno es en realidad una llamada a función, este código en particular puede terminar con una condición de fuera de rango:

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

La asignación a variables temporales te permite asegurarte de que el código del bloque interno solo se evalúe una vez.

Variables temporales

Una variable temporal almacena el valor de la string de código de un bloque interno de modo que el código solo se evalúe una vez y, luego, se puede hacer referencia al valor varias veces.

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`;
}

La llamada a getDistinctName toma el nombre de la variable que deseas y muestra un nombre que no entra en conflicto con ninguna variable definida por el usuario.

Reduce el código redundante

La desventaja de las variables temporales es que si el código del bloque interno es un valor y no una función o expresión, obtendrás un código redundante:

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

Para producir un código más limpio, puedes comprobar si el código del bloque interno es un valor y solo incluir la variable temporal si no lo es.

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`;
}