Câu lệnh chặn các đối số lưu vào bộ nhớ đệm

Đôi khi, trình tạo mã khối cần tham chiếu nhiều lần mã của khối bên trong.

Ví dụ: nếu có một khối in ra phần tử cuối cùng của danh sách, bạn cần truy cập vào mã danh sách nhiều lần:

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

Tuy nhiên, điều này có thể gây ra sự cố nếu giá trị kết quả của mã của khối bên trong không nhất quán hoặc có tác dụng phụ. Ví dụ: nếu mã bên trong thực sự là một lệnh gọi hàm, thì mã cụ thể này có thể kết thúc bằng một điều kiện nằm ngoài phạm vi:

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

Việc chỉ định cho các biến tạm thời cho phép bạn đảm bảo rằng mã của khối bên trong chỉ được đánh giá một lần.

Biến tạm thời

Biến tạm thời lưu trữ giá trị chuỗi mã của một khối bên trong để mã này chỉ được đánh giá một lần, sau đó giá trị có thể được tham chiếu nhiều lần.

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

Lệnh gọi getDistinctName lấy tên biến mà bạn muốn và trả về một tên không xung đột với bất kỳ biến nào do người dùng xác định.

Giảm mã thừa

Nhược điểm của các biến tạm thời là nếu mã của khối bên trong là một giá trị chứ không phải là một hàm hay biểu thức, thì bạn sẽ nhận được mã thừa:

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

Để tạo mã sạch hơn, bạn có thể kiểm tra xem mã của khối bên trong có phải là một giá trị hay không và chỉ thêm biến tạm thời nếu biến không phải là giá trị.

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