Czasami generator kodu blokowego musi odwoływać się do kodu swojego wewnętrznego kodu zablokować wiele razy.
Jeśli np. masz blok, który drukuje ostatni element listy, musisz wielokrotnie korzystać z 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 wartość wynikowa kodu wewnętrznego bloku to niespójne lub mają skutki uboczne. Jeśli na przykład wewnętrzny kod to wywołaniem funkcji, ten konkretny kod może skończyć się warunkiem „poza zakresem”:
print(randomList()[randomList().length - 1]);
Przypisanie do zmiennych tymczasowych pozwala upewnić się, że kod wewnętrznego bloku oceniane tylko raz.
Zmienne tymczasowe
Zmienna tymczasowa przechowuje wartość ciągu kodu wewnętrznego bloku, dzięki czemu kod jest oceniany tylko raz; wartość może być odwołana do wielu wartości 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 funkcji getDistinctName
przyjmuje odpowiednią nazwę zmiennej i zwraca
, która nie koliduje z żadnymi zmiennymi zdefiniowanymi przez użytkownika.
Ogranicz zbędny kod
Wadą zmiennych tymczasowych jest to, że jeśli kod wewnętrznego bloku jest wartością zamiast funkcji czy wyrażenia otrzymasz kod, który jest nadmiarowy:
// Assigning to temp_list is unnecessary.
var temp_list = foo;
print(temp_list[temp_list.length - 1]);
Aby wygenerować bardziej przejrzysty kod, możesz sprawdzić, czy kod wewnętrznego bloku jest wartością. uwzględniaj tylko zmienną tymczasową.
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`;
}