为什么我无法在Chrome(和Safari)中将console.log作为回调参数传递?

时间:2015-08-09 23:43:53

标签: javascript function google-chrome firefox jquery-deferred

以下代码段会在Chrome(和Safari)中生成错误,但在Firefox中可用。

我希望在javascript控制台中显示2个数字,但在Chrome中我只得到第一个,然后是Uncaught TypeError: Illegal invocation

// a generic promise that return a random float
var makePromise = function() {
  return $.Deferred().resolve(Math.random());
}

// This works in all browsers
makePromise().then(function(d) {
  console.log(d);
});
// This works in firefox only
makePromise().then(console.log);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

为什么会这样?

旁注:我的问题与this question不一样。

更新

感谢评论和回答使用console.log作为回调,需要做

makePromise().then(console.log.bind(console));

2 个答案:

答案 0 :(得分:7)

在Chromebook中我可以按如下方式复制问题:

function do4(cb){ cb(1); cb(2); cb(3); cb(4); }

do4(console.log)
VM1491:2 Uncaught TypeError: Illegal invocation
    at do4 (<anonymous>:2:19)
    at <anonymous>:2:12
    at Object.InjectedScript._evaluateOn (<anonymous>:905:140)
    at Object.InjectedScript._evaluateAndWrap (<anonymous>:838:34)
    at Object.InjectedScript.evaluate (<anonymous>:694:21)do4 @ VM1491:2(anonymous function) @ VM1552:2InjectedScript._evaluateOn @ VM1288:905InjectedScript._evaluateAndWrap @ VM1288:838InjectedScript.evaluate @ VM1288:694

但这很好用,确实指出了问题:

do4(console.log.bind(console))
VM1491:2 1
VM1491:2 2
VM1491:2 3
VM1491:2 4

为什么?

在Chrome中,console本身会返回原型Object的{​​{1}},  看:

Console

console Console {} memory: MemoryInfo__proto__: Console 视为console似乎很奇怪,但它确实如此。 Object还有其他一些较少使用的方法,这些方法不像console那样频繁使用,但记录在MDN Console DocsChrome Console Docs

在这里,我们得到了一个可以让人迷惑的大Javascript主题:

Javascript方法是未绑定方法。也就是说,这些方法不受任何特定对象的约束。

所以console.log是一个函数,但它只是函数,不保留console.logthis的绑定。

变量绑定在一个函数的代码中由一个神奇的console变量引用,该变量可以使用function.bindfunction.apply进行设置。

当调用this时,JS会将功能代码console.log()绑定到this对象。但是当console仅作为函数传递时,它不会执行绑定,因此其他代码可以更灵活地使用它。使用console.log和许多其他方法时,这种行为很不方便,但在某些情况下会增加所需的灵活性。

答案 1 :(得分:0)

尝试使用deferred.resolveWith()

&#13;
&#13;
// a generic promise that return a random float
var makePromise = function() {
  // set `this` to `window.console` , 
  // pass arguments within array
  return $.Deferred().resolveWith(window.console, [Math.random()]);
}

// This works in all browsers
makePromise().then(console.log)
//.then(function(d) {
//  console.log(d);
//});
// This works in firefox only
makePromise().then(console.log);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
&#13;
&#13;
&#13;