【问题标题】:Designing javascript function accepting string or function设计接受字符串或函数的javascript函数
【发布时间】:2013-01-08 09:49:26
【问题描述】:

特别是在 Javascript 中,API 公开接受字符串或特定参数函数的函数是很常见的。字符串提供“已经初始化”的值,而函数在运行时产生值。

// Call foo with known value
api.foo('bar')
// or defer value determination to run-time
api.foo(function() { return 'bar'; }

这更灵活,有时传递给这些 API 调用的参数直到运行时才知道,例如

api.foo(function() { return prompt('foo or bar ?'); });

这种方法在某种程度上保留给面向公众的函数(因为它们引入了更复杂的签名并且可能有陷阱 - 最好保持它们的数量少),但是,编写这样的函数有什么好的习惯用法?

类似的东西

api = {
  // "public" function
  func: function(a) {
    if (typeof(a) == 'function')
      return this._func(a());
    else
      return this._func(a);
  },
  // Actual implementation
  _func: function(a) {
    [...]
  }
}

应该可以,但肯定有更高效/优雅的替代方案。有什么想法吗?

更新:在@camus 的 cmets 之后(以及一个现在已经消失但相关的答案),这里有一个更新澄清了我的意图并解释了这与 API 的关系

请考虑,在编写函数时,我们不知道会以哪种方式调用它,并且我们不想对其进行限制性假设。该函数被设计为通用的,因此可以使用不同的签名多次调用它。我们可以强制调用者使用字符串,但是让一个返回字符串的函数来完成这项工作会很方便。这个函数可以传递额外的参数(比如一个索引,...),这当然是非常特定于 API 的上下文,但一般的想法是“我如何处理字符串和函数-返回-a - 以优雅的方式字符串参数?”。

【问题讨论】:

  • 你和那个解决方案很搭:jQuery的on事件绑定是这样实现的:github.com/jquery/jquery/blob/…基本上是一个嵌套的if/else来解决调用混乱。
  • 立即执行函数有什么意义?作为参数传递的函数应该用作延续,否则没有意义。为什么不直接在代码中做 fun(my_func()) 然后......在第一个例子中(“将值确定推迟到运行时”)它也没有什么意义,因为你必须使用闭包来改变传递函数的结果。在大多数情况下,传递函数的结果是可以预测的。
  • 你不应该用下划线 (_) 开始你的变量,因为下划线通常是指一个私有变量,_func 不是。

标签: javascript function signature


【解决方案1】:

这是一个简单的实现方法:

api = {
  // "public" function
  func: function(a) {
    if (typeof a == 'function') {
      a = a();
    }
    // rest of function
  }
}

【讨论】:

  • typeof a(无括号)
  • @David:我已经使用typeof() 很长时间没有realizing。谢谢。
【解决方案2】:

我会选择:

api = {
  func: function(a) {
    if(typeof a == 'function') a = a.call(this); // Transmit api as scope for a, may be useful for accessing api tools ...

    // Process a ...
  }
};

【讨论】:

  • 向函数传递参数确实是一件非常有用的事情。某些 API 将按照您的建议使用 this 传输其特定上下文,但也使用索引(用于数据收集)或与其范围相关的任何内容。
  • 接受这个答案,因为@yent 需要比@Barmar 更多的代表 :) 实际上,因为this 参数 - 这是一个很好的远见,这个问题不需要。
【解决方案3】:
api = {
  func: function( a ) {
    typeof a == 'function' && a.call( this, arguments ); 
  }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    • 2018-05-20
    • 2012-11-23
    • 1970-01-01
    相关资源
    最近更新 更多