Skip to content

Latest commit

 

History

History
78 lines (56 loc) · 3.39 KB

File metadata and controls

78 lines (56 loc) · 3.39 KB

缓存参数

从块生成代码时,经常会发现需要多次使用子块的返回值。考虑一个值块,该值块查找并返回列表的最后一个元素。该块本身将有一个输入(一个列表),并返回一个值(最后一个元素)。这是 JavaScript 的生成器:

var code = arg0 + '[' + arg0 + '.length - 1]';

如果 arg0 是变量名,则此生成器返回完全可接受的 JavaScript:

aList[aList.length - 1]

但是,如果 arg0 是函数调用,则此生成器可能具有意外行为。考虑以下代码:

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

返回的两个值的长度可能不同,从而导致超出范围条件。此外,如果函数调用具有副作用,则不希望两次调用它。

有两个解决方案。语句块应使用临时变量。值块应使用实用程序功能。

临时变量

最简单的解决方案是将有问题的输入分配给一个临时变量。必须注意,此变量不会偶然与现有变量发生冲突。以下代码显示了一个语句块中的临时变量示例,该变量警告列表的最后一个元素。

var listVar = Blockly.JavaScript.variableDB_.getDistinctName(
    'temp_list', Blockly.Variables.NAME_TYPE);
var code = 'var ' + listVar + ' = ' + arg0 + ';\n';
code += 'alert(' + listVar + '[' + listVar + '.length - 1]);\n';

getDistinctName 调用采用所需变量名称(“temp_list”)的参数,并将返回要使用的非冲突名称(可能是“temp_list2”)。

临时变量的缺点是,如果令人讨厌的输入已经是一个变量,则将生成冗余代码:

var temp_list = foo;
alert(temp_list[temp_list.length - 1]);

要生成更简洁的代码,请检查有问题的输入是否为简单文字,并相应地生成代码:

if (arg0.match(/^\w+$/)) {
  var code = 'alert(' + arg0 + '[' + arg0 + '.length - 1]);\n';
} else {
  var listVar = Blockly.JavaScript.variableDB_.getDistinctName(
      'temp_list', Blockly.Variables.NAME_TYPE);
  var code = 'var ' + listVar + ' = ' + arg0 + ';\n';
  code += 'alert(' + listVar + '[' + listVar + '.length - 1]);\n';
}

有关临时变量的工作示例,请参见 Blockly.JavaScript.controls_forEach

临时变量在语句块(在这种情况下为警报)中效果很好,在语句块中生成的代码可能跨越多行。但是,它们不能在必须位于一行中的值块中使用。对于值块,必须使用实用程序功能而不是临时变量。

实用功能

定义实用程序功能是一种创建功能块的强大方法,该功能块的工作级别高于基础语言。除非使用了实用程序功能,否则它们不会生成,并且无论使用多少次,它们只会生成一次。

var functionName = Blockly.JavaScript.provideFunction_(
    'list_lastElement',
    [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '(aList) {',
      '  // Return the last element of a list.',
      '  return aList[aList.length - 1];',
      '}']);
// Generate the function call for this block.
var code = functionName + '(' + arg0 + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];

在上面的示例中,我们要求定义一个名为 list_lastElement 的实用程序函数(尽管实际名称可能有所不同,以避免与用户变量冲突)。 有关实用程序功能的工作示例,请参见Blockly.JavaScript.text_endString