A instrução bloqueia argumentos de armazenamento em cache

Às vezes, o gerador de código de bloco precisa referenciar o código do bloco interno várias vezes.

Por exemplo, se você tiver um bloco que mostra o último elemento de uma lista, será necessário acessar o código da lista várias vezes:

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

Mas isso pode causar problemas se o valor resultante do código do bloco interno for inconsistente ou tiver efeitos colaterais. Por exemplo, se o código interno for, na verdade, uma chamada de função, esse código específico poderá acabar com uma condição fora do intervalo:

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

A atribuição a variáveis temporárias permite garantir que o código do bloco interno seja avaliado apenas uma vez.

Variáveis temporárias

Uma variável temporária armazena o valor da string de código de um bloco interno para que o código seja avaliado apenas uma vez e, em seguida, o valor possa ser referenciado várias vezes.

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

A chamada getDistinctName recebe o nome da variável que você quer e retorna um nome que não entre em conflito com nenhuma variável definida pelo usuário.

Reduzir código redundante

A desvantagem das variáveis temporárias é que, se o código do bloco interno for um valor, e não uma função ou expressão, você receberá um código redundante:

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

Para produzir um código mais limpo, verifique se o código do bloco interno é um valor e só inclua a variável temporária se não for.

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