문 블록 캐싱 인수

블록 코드 생성기가 내부 블록의 코드를 여러 번 참조해야 하는 경우가 있습니다.

예를 들어 목록의 마지막 요소를 출력하는 블록이 있다면 목록 코드에 여러 번 액세스해야 합니다.

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

그러나 내부 블록 코드의 결과 값이 일관되지 않거나 부작용이 있는 경우 문제가 발생할 수 있습니다. 예를 들어 내부 코드가 실제로 함수 호출인 경우 이 특정 코드는 범위를 벗어난 조건이 될 수 있습니다.

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

임시 변수에 할당하면 내부 블록의 코드가 한 번만 평가되도록 할 수 있습니다.

임시 변수

임시 변수는 내부 블록의 코드 문자열 값을 저장하여 코드가 한 번만 평가되고 이후 값이 여러 번 참조될 수 있도록 합니다.

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

getDistinctName 호출은 원하는 변수 이름을 사용하고 사용자 정의 변수와 충돌하지 않는 이름을 반환합니다.

중복 코드 감소

임시 변수의 단점은 내부 블록의 코드가 함수나 표현식이 아닌 값이면 중복된 코드가 발생한다는 것입니다.

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

더 깔끔한 코드를 생성하려면 내부 블록의 코드가 값인지 확인하고 값이 아닌 경우에만 임시 변수만 포함하면 됩니다.

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