0

So I was coding today and I found odd that

arguments.concat(someNumber);

gave me an error for undefined function. At first I thought that arguments might be some kind of native object for performance reasons, but in the end I found out it is in fact a plain javascript object and not an array or internal native object. I was left wondering if there is any special reason for that.

Hoffmann
  • 14,369
  • 16
  • 76
  • 91
  • 1
    It's really not a "plain JavaScript object". It's got special properties. – Pointy Oct 20 '14 at 16:23
  • 1
    [`arguments`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments) *is* a native object. What made you think it isn't? – Bergi Oct 20 '14 at 16:24
  • @Bergi yes it's a native object; sorry if my statement was unclear. The `arguments` object has [it's own section in the language spec](http://www.ecma-international.org/ecma-262/5.1/#sec-10.6). – Pointy Oct 20 '14 at 16:25
  • Note that `arguments` is still "array-like" and some of the Array methods will work. You just need to call them differently: `var args = Array.prototype.concat.slice(arguments);` By using `slice` in particular, you can effectively "copy" the arguments into a real array, at which point all of the methods are available directly on the array instance. – Platinum Azure Oct 20 '14 at 16:25
  • @Pointy @Bergi odd, `typeof arguments` is giving me `"object"` and `arguments instanceof Object` is giving me true in chrome. Shouldn't it show `[Native something]'? – Hoffmann Oct 20 '14 at 16:26
  • @Hoffmann: both happens for an `[]`, a `document` or a regex as well. If you want something special, try `""+arguments`: `"[object Arguments]"` – Bergi Oct 20 '14 at 16:27
  • Interesting, thank you Bergi – Hoffmann Oct 20 '14 at 16:29
  • Sadly the `typeof` operator is somewhat inadequate in JavaScript. @PlatinumAzure you're right, but it should be noted that most uses of the `arguments` object endanger runtime optimization, and passing `arguments` out of a function (like, to `.slice()`) is one of those uses. – Pointy Oct 20 '14 at 16:29
  • [See this interesting article (which appears to be kept up-to-date, at least for now).](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments) – Pointy Oct 20 '14 at 16:32
  • @Pointy you know if there is any performance degradation on using `someFunction.apply(someObject, arguments)`? I use that kind of expression all the time... – Hoffmann Oct 20 '14 at 16:34
  • @Hoffmann that article I linked says it's OK, towards the end of that section. However it says it in a somewhat confusing way; maybe I'll log an issue since it is on GitHub after all :) – Pointy Oct 20 '14 at 16:35
  • 1
    `function toType(x) { return ({}).toString.call(x).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); }` is a nice 1-line replacement for `typeof` that I use regularly. – Andy Oct 20 '14 at 16:35
  • @Andy: [There are simpler ways](http://stackoverflow.com/a/332429/1048572) without regex – Bergi Oct 20 '14 at 17:07

1 Answers1

1

The arguments object is special ("exotic" in Harmony parlance) because it maintains the live connection between its own numeric properties and scope variables:

function x(a) {
    arguments[0] = 42;
    document.write(a);
}

x(10)

To support this functionality, arguments needs to override a lot of stuff from the default object. That's why it's a separate type.

georg
  • 211,518
  • 52
  • 313
  • 390
  • I wonder why they did it like this, this breaks all the rules of normal javascript objects. I assume it is for performance reasons (avoiding allocating the function parameters twice). – Hoffmann Oct 21 '14 at 12:57