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 mã của bên trong chặn nhiều lần.

Ví dụ: nếu bạn có một khối in phần tử cuối cùng của một 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`;
}

Nhưng đ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 là 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, mã cụ thể này có thể kết thúc với điều kiện nằm ngoài dải ô:

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

Việc chỉ định cho các biến tạm thời giú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 khối bên trong để mã 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 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 hàm hoặc biểu thức, 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ỉ bao gồm biến tạm thời nếu không có biến.

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