Google Scripts/Basic JavaScript -调试器修复了这个问题

Google Scripts/Basic JavaScript - Issue fixed by debugger

本文关键字:问题 调试器 Scripts Basic JavaScript Google      更新时间:2023-09-26

我正在为Google Sheets添加Google Scripts,但我试图在实际将其设置在工作表上之前让脚本工作。如果我在extractNumbers函数中设置了一个断点,下面的代码可以正常工作。如果我只执行没有断点的代码,我会得到一个错误:

TypeError: Cannot call method "replace" of undefined。(第36行,文件")

代码如下:

var myVar = phoneCheck("a1","a2","o1","o2");
Logger.log(myVar);
function phoneCheck(newCell,newHome,oldCell,oldHome) {
  Logger.clear();
  var newCell = extractNumbers(newCell);
  var oldCell = extractNumbers(oldCell);
  var newHome = extractNumbers(newHome);
  var oldHome = extractNumbers(oldHome);
  if (newCell === oldCell) {
    return newCell;
    exit;
  } else if (newCell === oldHome && newHome === oldCell) {
    return oldCell;
    exit;
  }
  if (newCell === '' && oldCell !== '' ) {
    return oldCell;
    exit;
  }
  if (newCell !== oldCell && newCell !== oldHome) {
   return newCell;
    exit;
  }
  return "No value found";
  exit;
}
function extractNumbers(input) {
  Logger.log(input);
  var str = input;
  return str.replace( /'D+/g, '');
}

现在我意识到我的if/then逻辑有点不优雅,但对于我的目的来说,快速和肮脏是好的。我只需要它运行。

还有,我读过其他JavaScript新手程序员在代码执行顺序方面有类似的问题。如果有人想链接到一个简洁的来源针对非高级观众,这将是伟大的太。谢谢!

EDIT:我把我的代码放入一个新的fiddle,它工作得很好,但它继续失败在谷歌脚本编辑器,除非运行在调试模式与断点。问题似乎是,函数参数不可用于函数,除非有一个断点。任何人都可以访问谷歌脚本,可以尝试从https://jsfiddle.net/hrzqg64L/?

没有一个建议得到你的问题的根源-也没有你的答案,虽然你已经避免了这个问题,把周围的一切。

没有AJAX,没有异步行为——比这更简单。"隐藏参数"同样是转移注意力的方法。糟糕的编码习惯,是的——但不是这里的一个因素。

如果有人想链接到一个针对非高级受众的简明来源,那也很好。

对不起,没有这样的事。我可以解释这是怎么回事,但不能保证新手也能看懂。

例外

让我们澄清一下是什么原因导致了您观察到的异常或抛出错误。

如前所述,extractNumbers()将抛出一个异常,如果它有一个空参数(或任何非字符串参数)传递给它。如果你选择extractNumbers(),然后点击"run",你会得到:

TypeError: Cannot call method "replace" of undefined。(第36行,文件")

这是告诉你,在第36行,即return str.replace( /'D+/g, '');,变量str包含一个对象undefined(…)并且没有replace()方法)。

对于防弹代码,您将检查参数以确保它们有效,并适当地处理它们。有时会使用有效的默认值,有时可能会返回错误或抛出异常,这更明确地说明了参数问题。

在Google的调试器中运行代码

在Google的调试器中运行代码的唯一方法是选择一个函数,然后选择"运行"或"调试"。假设您发布了所有代码,您只有两个函数可供选择:

  • phoneCheck()
  • extractNumbers()

每当Google Apps Script运行脚本的任何部分时,整个脚本被加载并扫描以找到所有符号&检查语法。所有符号的作用域也会被记录下来,函数和全局符号(任何闭包或代码块之外的符号)之间的依赖关系也会被记录下来。

那需要一些时间。当被要求执行一个特定的函数时,为了加快速度,全局符号只有在它们是被请求函数或它可能调用的函数的依赖项时才会求值。还有另一种情况会触发对全局符号的求值,那就是调试器可能需要停止并显示值。

当这种情况发生时,闭包之外的任何代码(例如函数之外的代码)都将被执行。

为什么当设置断点时它工作?

如前所述,只要有一个断点集就会触发对全局符号的求值。

你用几行不在任何闭包中的代码开始这个脚本:

var myVar = phoneCheck("a1","a2","o1","o2");
Logger.log(myVar);

这段代码使phoneCheck()带参数的唯一正确调用。因为myVar被求值,所以phoneCheck()被带参数调用,然后带定义的参数调用extractNumbers()

不幸的是,由于调试器的工作方式,您不能选择自己运行该代码。你需要依赖这些副作用行为。

如何解决这个问题?

简单。不要依赖全局代码来调用测试中的函数。相反,应该编写一个显式的测试函数,并调用它。

function test_phoneCheck() {
  var myVar = phoneCheck("a1","a2","o1","o2");
  Logger.log(myVar);
}

终于找到问题了,但是我不太明白。

这个问题让我想到了作用域,以及它在Google Script环境中可能会有什么不同。我认为一个简单的解决方案是将整个脚本包含在自己的void函数中,并且它工作了!另外,我用一个数组简化了脚本:

function init () {
  var numberArray = ["a3", "a2", "o3", "o10"];
  var myVar = phoneCheck(numberArray);
  Logger.log(myVar);
  function phoneCheck(myArray) {
    var phoneString = '';
    Logger.clear();
    var arrayLength = myArray.length;
    for (i = 0; i < arrayLength; i++) {
      phoneString += myArray[i].replace(/'D+/g, '');
    }
    return phoneString;
  }
}

另外,我意识到这个脚本的功能与原来的不同,但我真的只是想解决这个问题。现在我有了,我可以正确地完成脚本了。

谢谢大家的建议!我学到了很多好东西,即使它们最终不是答案。