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