Why I can't pass console.log as a callback argument in Chrome (and Safari)?

后端 未结 2 1089
夕颜
夕颜 2021-01-17 22:25

The following snippet will produce an error in Chrome (and Safari) while it works in Firefox.

I\'d expect to have 2 numbers shown in javascript console, but in Chrom

相关标签:
2条回答
  • 2021-01-17 23:08

    Try utilizing deferred.resolveWith()

    // 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);
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
    </script>

    0 讨论(0)
  • 2021-01-17 23:12

    In a chromebook I can duplicate the problem as follows:

    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
    

    But this works fine, and indeed points toward the problem:

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

    Why is that?

    In chrome, console by itself returns an Object of prototype Console, look:

    console
    Console {} memory: MemoryInfo__proto__: Console
    

    It may seem odd thinking of console as an Object, but it is. console has several other lesser-used methods that are not used as often as console.log but are documented in MDN Console Docs and Chrome Console Docs

    And here we get to a big Javascript-ism that can confuse people:

    Javascript methods are unbound methods. That is, the methods are not bound to any particular object.

    So console.log is a function, but it is the function only and does not preserve its binding of this to console.

    The variable binding is referred to inside a function's code by a magic this variable, which can be set with function.bind or function.apply.

    When console.log() is called, JS does the binding of the function code's this to the console object. But when console.log is merely passed as a function, it does not do the binding, so that other code can use it more flexibly. This behavior is inconvenient with console.log and many other methods, but in some cases adds needed flexibility.

    0 讨论(0)
提交回复
热议问题