A instrução bloqueia argumentos de armazenamento em cache

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

Por exemplo, se você tem um bloco que imprime o último elemento de uma lista, precisa 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 inconsistentes ou têm efeitos colaterais. Por exemplo, se o código interno for uma chamada de função, esse código específico pode acabar com uma condição fora do intervalo:

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

A atribuição a variáveis temporárias permite que você se certifique de 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 é avaliado apenas uma vez e, em seguida, o valor pode 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 usa o nome da variável que você quer e retorna uma que não entre em conflito com nenhuma variável definida pelo usuário.

Reduzir o 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ê recebe 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, você pode verificar se o código do bloco interno é um valor e inclua a variável temporária apenas 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`;
}