Pernyataan memblokir argumen caching

Terkadang generator kode blok Anda perlu mereferensikan kode di bagian dalamnya beberapa kali.

Misalnya, jika Anda memiliki blok yang mencetak elemen terakhir dari daftar, Anda perlu mengakses kode daftar beberapa kali:

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

Tapi ini dapat menyebabkan masalah jika nilai dari kode blok bagian dalam yang dihasilkan tidak konsisten, atau memiliki efek samping. Misalnya, jika kode {i>inner<i} sebenarnya panggilan fungsi, kode khusus ini dapat berakhir dengan kondisi di luar rentang:

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

Menetapkan variabel sementara memungkinkan Anda memastikan bahwa kode blok bagian dalam hanya dievaluasi sekali.

Variabel sementara

Variabel sementara menyimpan nilai string kode blok bagian dalam sehingga kode hanya dievaluasi sekali, lalu nilainya dapat dirujuk kali.

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

Panggilan getDistinctName menggunakan nama variabel yang Anda inginkan, dan menampilkan nama yang tidak bertentangan dengan variabel buatan pengguna.

Mengurangi kode yang berlebihan

Kelemahan dari variabel sementara adalah bahwa jika kode blok bagian dalam adalah nilai dan bukan fungsi atau ekspresi, Anda akan mendapatkan kode yang redundan:

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

Untuk menghasilkan kode yang lebih bersih, Anda dapat memeriksa apakah kode blok bagian dalam berupa nilai, dan hanya sertakan variabel sementara jika tidak.

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