【问题标题】:How do I wrap a call to a Google Apps Script function that accepts unlimited arguments如何包装对接受无限参数的 Google Apps 脚本函数的调用
【发布时间】:2013-04-12 13:24:21
【问题描述】:

Logger.log() 和 Utility.formatString() 等一些 Google Apps 脚本函数接受无限参数。

我想包装对 Logger.log() 或 Utility.formatString() 的调用,以便在最里面的函数调用中,我可以在结果字符串前面加上时间戳和我自己的文本。通常你只需 .apply 当前模块的 ags 到函数,但在我的测试中,这不能按预期工作。它会导致错误 TypeError: Cannot find default value for object. (line 14, file "Code") 其中 looks 来自 java/server 端。

这是我用于测试的代码。问题:

  1. 这是这些 Apps 脚本方法中的错误吗?
  2. 是否有解决方法或替代方法来实现我的目标?

如果是错误,我也会将其提交到问题跟踪器跟踪器中

function testMyLogger() {
  myLogger('Testing %s %s %s', 'one', 2, 'three'); 
}

function myLogger()  {
  // do common things like prefix a timestamp to the first arg
    var logdate = Utilities.formatDate(new Date(), Session.getTimeZone(), "yyyy-MM-dd HH:mm:ss");
    arguments[0]= logdate + " " + arguments[0]; 

  Logger.log.apply(this, arguments); 
  // At the above line I get error "TypeError: Cannot find default value for object. (line 14, file "Code")"
  // but I expected '<timestamp> Testing one 2.0 three' to the log (View > Logs...)
}

【问题讨论】:

    标签: javascript google-apps-script rhino


    【解决方案1】:

    试试Logger.log.apply(Logger, arguments);

    【讨论】:

    • 抱歉,克里斯,我更正了那个调用并更新了错误消息(我尝试了一堆变体,最初在这里写了不正确的一个。
    • 感谢您尝试解决此问题,但这也会返回相同的错误“TypeError:找不到对象的默认值”。
    • 仅供参考:现在应该修复底层错误。现在这是正确(有效)的答案。
    【解决方案2】:

    不幸的是,这不起作用,但applymap 通常不能很好地与主机对象上的函数一起使用(有时在浏览器中也是如此)。然而,这个可怕的丑陋黑客会为你解决问题。将您的 Logger.log.apply 替换为:

    for (var i = 0, arr = []; i < arguments.length; ++i)
      arr.push('arguments[' + i + ']');
    eval('Logger.log(' + arr.join() + ')');
    

    或者,如果有人更喜欢简洁而不是可读性:

    eval('Logger.log(' + [].slice.call(arguments, 0)
        .map(function(x, y){ return 'arguments[' + y + ']'; }).join() + ')');
    

    更新

    或者我们可以,你知道,只是修复错误 :)

    我夸大了原始错误的严重性:callapply 现在实际上适用于应用程序脚本宿主对象上 95% 的方法,但您碰巧遇到了当前不起作用的方法之一。不幸的是,我无法向您解释这种模式,因为我知道哪些模式可以在不参考我们内部代码的情况下工作。幸运的是,我的一位优秀同事诊断出这个问题并已经解决了它。 Logger.log.apply(Logger, ...) 将在一两个版本中开始工作。请留意发行说明。

    【讨论】:

    • 不要那样做。做Logger.log.apply(Logger..。请记住,apply 的第一个参数决定了函数内的关键字this 指向什么。它几乎总是该方法所属的对象,而几乎从来不是调用范围内的当前 this 值。对其工作原理的误解是为什么人们认为 callapply 不能很好地与原生对象一起工作 - 这不是真的
    • 不,规范的解决方案目前确实无法在 Apps 脚本中运行。我说作为工程团队的一员 :) 但您可以轻松地自己验证;我们不支持应用在我们的原生对象中的方法上。
    • 此外,在其他地方也常常不是这样(例如,出于类似原因,您不能在 IE9 中的 console.log 上使用 apply)。本机对象的实现有时比您预期的要混乱,并且 ES 规范中有关本机可调用对象的一些回旋余地,这使得实现者在技术上允许这样做。
    • 我已经测试并接受了@CoreyG 的解决方法。我使用了第一个,因为明年我在震惊中偶然发现它时可以阅读它。顺便说一句,Corey 一直在供应商(谷歌)的这个产品的团队中工作,所以我很高兴黑客是必需的解决方法。它是否会/可以在 AppsScript 原生 Logger 对象上工作是实现者的事情
    • 仅供参考:现在应该修复底层错误。使用 callapply(干净的解决方案)似乎可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 2019-02-01
    • 1970-01-01
    • 2020-11-25
    • 2014-09-17
    相关资源
    最近更新 更多