Instrukcja blokuje argumenty buforowania

Czasami generator kodów blokowych musi wielokrotnie odwoływać się do kodu swojego wewnętrznego bloku.

Jeśli np. masz blok, w którym wyświetla się ostatni element listy, musisz wielokrotnie przechodzić do kodu listy:

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

Może to jednak powodować problemy, jeśli wynikowa wartość kodu bloku wewnętrznego jest niespójna lub ma to skutki uboczne. Jeśli np. kod wewnętrzny jest w rzeczywistości wywołaniem funkcji, ten konkretny kod może zawierać warunek „poza zakresem”:

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

Dzięki przypisaniu do zmiennych tymczasowych kod bloku wewnętrznego jest sprawdzany tylko raz.

Zmienne tymczasowe

Zmienna tymczasowa przechowuje wartość ciągu kodu bloku wewnętrznego, dzięki czemu jest on oceniany tylko raz, po czym może się do niej odwoływać wiele razy.

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

Wywołanie getDistinctName przyjmuje wybraną nazwę zmiennej i zwraca nazwę, która nie jest sprzeczna ze zmiennymi zdefiniowanymi przez użytkownika.

Zmniejsz zbędny kod

Wadą zmiennych tymczasowych jest to, że jeśli kod bloku wewnętrznego jest wartością, a nie funkcją czy wyrażeniem, otrzymasz kod, który jest zbędny:

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

Aby wygenerować czystszy kod, możesz sprawdzić, czy kod bloku wewnętrznego jest wartością. Uwzględnij tylko zmienną tymczasową, jeśli nie jest.

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