Anweisung blockiert das Caching von Argumenten

Manchmal muss der Blockcode-Generator mehrmals auf den Code des inneren Blocks verweisen.

Wenn Sie beispielsweise einen Block haben, mit dem das letzte Element einer Liste ausgegeben wird, müssen Sie mehrmals auf den Listencode zugreifen:

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

Dies kann jedoch zu Problemen führen, wenn der Ergebniswert des Codes des inneren Blocks inkonsistent ist oder Nebenwirkungen hat. Wenn der innere Code beispielsweise tatsächlich ein Funktionsaufruf ist, kann dieser Code am Ende zu einer Bedingung außerhalb des Bereichs führen:

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

Durch die Zuweisung temporärer Variablen können Sie dafür sorgen, dass der Code des inneren Blocks nur einmal ausgewertet wird.

Temporäre Variablen

Eine temporäre Variable speichert den Wert des Codestrings eines inneren Blocks, sodass der Code nur einmal ausgewertet wird und dann mehrmals auf den Wert verwiesen werden kann.

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

Der Aufruf getDistinctName übernimmt den gewünschten Variablennamen und gibt einen Namen zurück, der nicht mit benutzerdefinierten Variablen in Konflikt steht.

Redundanten Code reduzieren

Der Nachteil temporärer Variablen besteht darin, dass Sie redundanten Code erhalten, wenn es sich beim Code des inneren Blocks um einen Wert und nicht um eine Funktion oder einen Ausdruck handelt:

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

Um einen saubereren Code zu generieren, können Sie prüfen, ob der Code des inneren Blocks ein Wert ist, und die temporäre Variable nur einschließen, wenn dies nicht der Fall ist.

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