6

I have added a function using Function.prototype.func = ... to Function but in Firefox it has not been added console.log:

Function.prototype.func = function () { return this.toString(); };
alert(typeof console.log.func); // in FF: undefined, in Chrome: function

Is it a bug or is there any reason for that?

Ali Shakiba
  • 20,549
  • 18
  • 61
  • 88
  • 3
    Perhaps it's because `console` is a *host object*, which means it is not bound by specification rules -- see [What is the difference between native objects and host objects?](http://stackoverflow.com/questions/7614317/what-is-the-difference-between-native-objects-and-host-objects) – apsillers May 03 '13 at 16:56
  • @apsillers thanks, I'm trying other host objects, but it seems they don't have this problem. – Ali Shakiba May 03 '13 at 17:02

1 Answers1

2

It is quite telling that in Firefox:

var foo = function() {}
foo.__proto__ == Function.prototype;

is true, whereas the statements:

console.log.__proto__ == Function.prototype;
console.log instanceof Function;

are both false.

Thus, console.log does not include Function.prototype in its prototype chain, so altering Function.prototype has no affect on console.log. This is perfectly fine, since console is a host object (rather than a native object in the ECMAScript specification) and may behave however Mozilla (or Google, or Microsoft, etc.) would like.

Why does this behavior exist? I'm not a Firefox dev, so I can't say for certain, but my best guess is that this was done specifically because console is a debugging tool. If you muck around with Function's prototype chain and then want to use console.log to verify what you're doing, it would be terrible if your debug reporting tool itself starting messing up and misreporting things to you.

EDIT:

The console functions have a separate prototype chain used by all of them:

console.log.__proto__ == console.dir.__proto__ // true
console.log.__proto__.func = 5;
console.dir.__proto__.func == 5  // true
Community
  • 1
  • 1
apsillers
  • 112,806
  • 17
  • 235
  • 239
  • hum, maybe that's the reason. btw, `console` is a host object but `console.log` is a function which I guess is not a host object. – Ali Shakiba May 03 '13 at 17:14
  • it's just curious that `typeof console.log` returns 'function', and `console.log.constructor` returns "Function()" and `console.log.constructor.name` returns "Function" yet it is not affected by `prototype` – CrayonViolent May 03 '13 at 17:15
  • @CrayonViolent that's why i'm really confused. – Ali Shakiba May 03 '13 at 17:16
  • I think apsillers' theory about *why* is plausible though. IOW it is a host object designed to look and feel like a native object for the purposes of testing that it exists, but it doesn't allow you to prototype it to keep you from messing with it – CrayonViolent May 03 '13 at 17:18
  • @CrayonViolent Yes, `Function.prototype` and `console.log.__proto__` are both anonymous functions, but they're not the *same* anonymous function. In fact, in FF, *all* `console` functions (`dir`/`log`/`err`/`warn`) share the same anonymous function as their parent prototype, but it's not the same anonymous function used for `Function.prototype`. – apsillers May 03 '13 at 17:20
  • 2
    FYI Firefox's console API is defined in https://github.com/mozilla-services/services-central-legacy/blob/master/dom/base/ConsoleAPI.js – Rob W May 03 '13 at 17:38
  • @apsillers The main reason that console.log does not have Function.prototype on the proto chain is that it's not a function at all. It's a callable proxy that enforces certain security restrictions before forwarding the call to the actual function. And no one bothered to make sure that when proxying a function the security membranes use Function.prototype as their prototype.... – Boris Zbarsky May 04 '13 at 06:51