admin管理员组文章数量:1323355
Consider the following strange behavior I noticed in one of my projects:
async function hello() {
return arguments;
}
When TypeScript's pilation target is set to es3
or es5
, the above file fails to pile with the following error:
error TS2522: The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5. Consider using a standard function or method.
2 return arguments;
~~~~~~~~~
However, with a higher pilation target (I've tested es2017
and esnext
) there is no error.
What is it about the arguments
keyword that prevents it from being used in async functions when TypeScript's pilation target is set to es3
or es5
?
A few notes:
- When replicated in modern JavaScript, this function does not throw an exception
- This behavior can only be replicated in
async
functions
My Hypothesis
I suspect that because Promise
needs to be polyfilled in es3
and es5
, the polyfill cannot support arguments
because it is dependant on the function callee.
Further reading: ES5.1 Spec § 10.6 Arguments Object
Consider the following strange behavior I noticed in one of my projects:
async function hello() {
return arguments;
}
When TypeScript's pilation target is set to es3
or es5
, the above file fails to pile with the following error:
error TS2522: The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5. Consider using a standard function or method.
2 return arguments;
~~~~~~~~~
However, with a higher pilation target (I've tested es2017
and esnext
) there is no error.
What is it about the arguments
keyword that prevents it from being used in async functions when TypeScript's pilation target is set to es3
or es5
?
A few notes:
- When replicated in modern JavaScript, this function does not throw an exception
- This behavior can only be replicated in
async
functions
My Hypothesis
I suspect that because Promise
needs to be polyfilled in es3
and es5
, the polyfill cannot support arguments
because it is dependant on the function callee.
Further reading: ES5.1 Spec § 10.6 Arguments Object
Share Improve this question asked Jun 27, 2019 at 20:19 brenbren 4,3443 gold badges30 silver badges44 bronze badges 4-
3
Your hypothesis sounds right. Remove
return arguments
than have a look at what the transpiler generates – Jonas Wilms Commented Jun 27, 2019 at 20:22 -
This has less to do with promises than rather with the generator continuations. I'm pretty sure you'll see the same error in a generator function. And to be honest, they should've been able to work around this, just like you can "work around" having no
arguments
orthis
in an arrow function. – Bergi Commented Jun 27, 2019 at 21:17 -
@bergi but whey should they? There is no use of
arguments
. – Jonas Wilms Commented Jun 27, 2019 at 21:21 -
@JonasWilms Just to follow the spec closely (which allows
arguments
) and not have users trip over error messages :-) – Bergi Commented Jun 27, 2019 at 21:32
3 Answers
Reset to default 6It's because Async functions get transpiled to a basic polyfilled implementation of generators; this implementation basically swaps out the body of your function to wrap it in another function, therefore any use of arguments
will never access the original arguments
of hello but instead of __generator
An example of this is below where hello which takes no arguments and generates the following in which the body of the function is wrapped in another function.
async function hello() {
console.log(arguments);
} // bees.....
function hello() {
return __awaiter(this, arguments, void 0, function () {
return __generator(this, function (_a) {
console.log(arguments);
return [2 /*return*/];
});
});
}
to re-iterate, console.log(arguments) has moved from the context of hello to the context of __generator meaning it would never behave how you expect it would. If you're targetting modern browsers (non-IE) you can set your pile target to ES6+ in which case this restriction will be removed.
Just use the spread operator
hello(...args: any[])
now you have an array or the arguments that were passed in.
You are absolutely right.
I'd like to share another point of view on why that does not work:
JavaScript has task based concurrency, which means that the code is broken into small "chunks" (tasks) and one of them gets executed at a time. If you have something asynchronous that gets divided into multiple tasks, one to start the async action and one to work with the results when the async action is done. Other tasks can run in the meantime, thus allowing for concurrency.
Now the smallest possible chunk of execution was (before async
) a function: A function always runs to pletion, you can't split up a function into multiple tasks.
With the introduction of the async
keyword, there are async
functions that don't run to pletion. They will be split up into smaller tasks (through await
s).
Now if you have to transpile an async function
into a regular function
you have one problem: You can't split up the tasks. Therefore you need multiple functions to represent one async function
:
async function(arg) { await a(); await b(); }
// bees
function(arg) { return a().then(function () { b(); }); }
Now as one can see that does not transpile exactly: While arg
was the argument of the only async
function, only the outer function has that arg
. However that is usually not a problem, wether you access arg
in the current scope or in an outer scope does not change the way things work (except you redeclare it).
However there is one thing that was changed, and which made up this answer: arguments
. As we have two functions we do have two arguments
objects. Now one could also mimic the arguments
object, but then you would have to use other unsupported newer language features (getters / setters, Proxies). And to be honest: You should not use arguments
and thus transpiling it is not worth the trouble.
本文标签: javascriptTypeScript arguments keyword in async functionsStack Overflow
版权声明:本文标题:javascript - TypeScript: arguments keyword in async functions - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742126589a2421970.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论