From 9.2.13 of the ES6 Spec Draft:
a. NOTE Arrow functions never have an arguments objects.
In fact, we should be capturing arguments from the first containing function expression and error if there is none. The correct emit for something like
function f() {
return () => arguments;
}
would be the following:
function f() {
var _arguments = arguments;
return () => _arguments;
}
As a practical point, both FF and V8 (with io.js --harmony_arrow_functions) have the same incorrect behavior as of now.
function foo() { return () => arguments[0]; } foo(5)(6) // 6
(Unchanged in strict mode.)
jstransform also does not capture the outer arguments object I think, but 6to5 does.
The spec has finalized on this point for more than a year now, so perhaps it's okay to go ahead with this and expect ES6-supporting browsers to fix their implementation. But perhaps the ES6 emit could implement a warning for this? "Warning - using an unbound arguments inside this arrow function may not behave as you expect. Consider explicitly binding the outer arguments object, or use a splat on the arrow function."
After discussing with @RyanCavanaugh, we've come to the decision that we should avoid changing the semantics of existing code and to give an error so as to push users away from using this construct. However, we will still emit so users will still be able to get this behavior if they desire.
This probably deserves some documentation since I'm guessing this will hit a few people.
It is now an error to reference the implicit arguments variable inside an arrow function.
The ECMAScript 6 specification says that no arguments variable is created for an arrow function. This means that in an arrow function inside a regular function, arguments refers to the _outer function's_ arguments.
Prior to the ES6 compile target, the TypeScript compiler would emit an arrow function as a regular function, and access to the arguments variable was allowed. The result is that arrow functions in pre-ES6 emitted code would be using the _inner_ arguments variable.
If ES3/ES5-targeted code that used arguments in an arrow function were changed to emit to ES6 and run on a compliant runtime, the behavior of those functions would change.
Notably, several runtimes today _do not respect this aspect of the ES6 spec_ and will incorrectly provide the inner function arguments as arguments.
When faced with this problem, we had a few choices:
1. Rewrite arguments like we do for this. We could change downlevel (ES3/ES5) arrow function emit to capture the outer arguments variable (same as the compiler does for this today) and emit ES6 arrow functions normally. This was considered too dangerous as it would change the semantics of existing code in dangerous ways.
2. Always downlevel-emit arrow functions. We could choose to not emit native arrow functions in ES6. This would preserve the non-compliant ES3/ES5 behavior where arguments refers to the arrow function's arguments. However, this would effectively fork TypeScript from JavaScript, making it impossible to safely transition ES6 code to TypeScript while preserving semantics. This is not an option.
3. Error today, maybe do option 1 later. This is where we've landed. Any TypeScript code that uses arguments today in an arrow function is necessarily expecting different behavior than what will eventually be supported in ES6 runtimes. Additionally, because many ES6 runtimes do not correctly handle arguments in arrow functions, it's not really safe to use arguments at all until the runtimes and the ES6 specification come into alignment. Code that wants to use arguments from the outer function should be capturing them (e.g. var args = arguments; in the outer function) so that they get the same behavior in compliant and non-compliant runtimes.
Once we're confident everyone has upgraded their code and sorted out the errors, and once the JavaScript runtimes start implementing the correct behavior, we can probably remove this error and start doing arguments rewriting in downlevel emit if it becomes a common pattern. This is likely several years away, practically speaking.
This issue has been cooperated into PR #1627
The 'arguments' object cannot be referenced in an arrow function. Consider using a standard function expression.
^ because I want this to show up in google search results :heart:
Hold on there, let's not forget the TypeScript diagnostic code, TS9002.
I'm getting code TS2496 in TypeScript 1.5 alpha:
TS2496: The 'arguments' object cannot be referenced in an arrow function. Consider using a standard function expression.
@robertpenner by design. Just use "function" instead of "()=>"
Or use rest args:
(...args) => args[0]
Instead of
() => arguments[0]
@basarat I get the same error even with function. I want to throw an error to validate that the minimum number of arguments are passed to a function, like below
function validateArgsCount(foo, bar, baz) {
if(arguments.length !== 3) {
throw new Error('Function expects exactly 3 arguments');
}
}
with error
The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5
But with TSC version 2.8.1.
Most helpful comment
The 'arguments' object cannot be referenced in an arrow function. Consider using a standard function expression.^ because I want this to show up in google search results :heart: