3

Hello I was reading "JavaScript: the definitive guide" 6th edition and tried one of the examples at 9.1 Classes and Prototypes.

function range (from, to) {
    var r = Object.create(range.methods);

    r.from = from;
    r.to = to;
    return r;
}

range.methods = {
    includes: function(x) { 
        return this.from <= x && x <= this.to; 
    },
    foreach: function(f) {
        for(var x = Math.ceil(this.from); x <= this.to; x++) 
            f(x);
    },
    toString: function() { 
        return "(" + this.from + "..." + this.to + ")"; 
    }
};

Loading this into console throws an error

Uncaught TypeError: Illegal invocation class.js:31. range.methods.foreach class.js:31 (anonymous function)

I guess intention of foreach method is to pass a function name as an argument

var r = range(1, 3);
r.foreach(console.log);

Any ideas how to fix this error?

DontVoteMeDown
  • 21,122
  • 10
  • 69
  • 105
It's like Booom
  • 127
  • 1
  • 8
  • I think that is something with `console.log`, [look](http://jsfiddle.net/NN38C/) – DontVoteMeDown Jul 29 '14 at 12:27
  • [Illegal Invocation error when console.log passed in a function](http://stackoverflow.com/questions/18426408/illegal-invocation-error-when-console-log-passed-in-a-function) – Brett Jul 29 '14 at 12:32

2 Answers2

9

It happens because you detached log method from console object, while console.log expects context (this) to be console, not Window as it becomes when you lose context. If you want to use console.log as a function you should explicitly tell it what context to use.

r.foreach(console.log.bind(console));

Function.prototype.bind is your friend in this case.

For future readers: ES6 style would also allow you to use arrow functions for this which would be even more concise:

r.foreach(x => console.log(x))
dfsq
  • 191,768
  • 25
  • 236
  • 258
4

Log cannot be called outside of the console object, you're passing in the function, but not the context.

r.foreach(function(a){
    console.log(a);
});

This works without any issues.

scragar
  • 6,764
  • 28
  • 36
  • Nice, it works, but why ? In fact it was called with the object console, right ? – DontVoteMeDown Jul 29 '14 at 12:29
  • @DontVoteMeDown When you pass a function you pass the function, but not the parent information, calling the function inside your loop then runs into an issue of the `this` object being the window instead of the console, and the function generates an error. – scragar Jul 29 '14 at 12:30