คำสั่งบล็อกอาร์กิวเมนต์การแคช

บางครั้งเครื่องมือสร้างโค้ดบล็อกต้องอ้างอิงโค้ดของบล็อกภายในหลายครั้ง

เช่น หากมีบล็อกที่พิมพ์องค์ประกอบสุดท้ายของรายการ คุณจำเป็นต้องเข้าถึงรหัสรายการหลายครั้ง ดังนี้

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