【问题标题】:Store reference to `call` function存储对 `call` 函数的引用
【发布时间】:2014-06-12 18:42:46
【问题描述】:

我今天早些时候注意到了一些奇怪的事情。我似乎无法存储对函数的call 属性的引用,然后执行它。示例:

var log = console.log;
log.call(console, 'This works'); 

var logCall = console.log.call;
logCall(console, 'This does not');

对我来说,这似乎是完全合法的 Javascript,但第二次调用总是给我undefined is not a function 的错误。随意使用它here,你会得到相同的结果。

那么为什么 Javascript 会阻止我以这种方式调用 call

编辑:在阅读了 SimpleJ 的答案后,我终于明白了。因此,我将通过如何使上述内容正常工作来更新此内容:

var log = console.log;
log.call(console, 'This works'); 

var logCall = console.log.call;
logCall.call(console.log, console, 'This works now too');

问题是console.log 接收到了正确的this 值,但console.log.call 没有得到正确的this 值。如您所见,我基本上必须执行console.log.call.call。显然你永远不会真正使用这样的代码,我只是好奇。

【问题讨论】:

  • 当您将console.log.call 存储在一个变量中时,它失去了对console.log 的引用,这意味着它不再知道在什么上执行参数。由于这个事实,我希望您的第一个示例在某些浏览器中失败(取决于所使用的浏览器如何定义 console.log)
  • 这与this 的工作方式有关:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…。由于您“通常”调用函数 (logCall()),this 要么指的是 window,要么是 undefinedFunction.prototype.call 不知道要作用于哪个函数。
  • 是的。这两个示例都不适用于 Chrome
  • FWIW,第一个示例在 Chrome 35 中工作。edit: 嗯,jsBin 可以工作,但是如果我直接在控制台中执行它就不行o_O跨度>
  • “那么为什么 Javascript 会阻止我以这种方式调用 call?” 再次了解 this 的工作原理:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…。这是一个很常见的问题,有一个简单的解释。

标签: javascript


【解决方案1】:

您需要保持绑定到控制台。试试这个:

var logCall = console.log.call.bind(console.log);
// example: logCall(console, "foobar");

var log = console.log.bind(console);
// example: log("foobar");

对于log的绑定引用。

编辑: jsfiddle:http://jsfiddle.net/67mfQ/2/

【讨论】:

  • 我的想法是一样的,但是当你尝试运行它时会产生TypeError: Illegal invocation....
  • 那是因为它是绑定调用。 call 的第一个参数是一个上下文,应该是 console
  • @SimpleJ:如果在console.log 上调用了.bind,你是对的。但它在console.log.call 上调用。
  • 为了让它在任何地方都能工作,你可能需要写console.log.call.bind(console.log, console)
  • @FelixKling 我以为他试图引用 call 而不是 log
【解决方案2】:

这是我最喜欢的 JavaScript 代码:

var bind = Function.bind;
var call = Function.call;

var bindable = bind.bind(bind);
var callable = bindable(call);

您可以使用bindable 函数获取对f.bind 的引用。同样,您可以使用callable 函数获取对f.call 的引用,如下所示:

var log = callable(console.log, console);

现在您需要做的就是像调用任何其他函数一样调用log 函数:

log("Hello World!");

就是这样。

【讨论】:

  • "callable(console.log, console);" 怎么样比“console.log.bind(console);”更好?
  • @dandavis:即使console.log 不是Function 实例(这种情况可能发生在 IE DOM 中),它也可以工作,但你是对的 - 只是更令人困惑。
  • @dandavis 在 5 行代码中,您获得了三个有用的函数 - bindablecallablelog。另外我觉得callable 函数比object.method.bind(object) 更具描述性。对我来说,这看起来很丑。
猜你喜欢
  • 1970-01-01
  • 2012-10-01
  • 2012-11-15
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多