Reputation: 72865
I'm writing several functions that take different types of parameters. As such, it's much simpler to just do:
var myFunc = function() {
var args = Array.prototype.slice.call(arguments)
}
...than to try to handle all the different possibilities directly in the parameter field of the function declaration, e.g.:
var myFunc = function(param1, param2, param3) {
if (param3) {
// etc.
}
}
Array.prototype.slice.call(arguments)
adds a lot to the code though, and reduces readability. I'm trying to figure out if there's a way to write a helper function that could accomplish the same thing as Array.prototype.slice.call()
, but cleaner and easier to read. I was trying something like:
var parseArgs = function() {
return Array.prototype.slice.call(arguments)
}
var foo = function() {
console.log(parseArgs(arguments))
}
foo('one', 'two', 'three')
// [Arguments, ['one', 'two', 'three']]
But obviously that doesn't work.
Upvotes: 4
Views: 1071
Reputation: 179046
A few shorthands for converting array-like objects to actual arrays in JS:
Alias Array.prototype.slice
:
(function (slice) {
...your code...
function someFunction() {
var args = slice.call(arguments);
...
}
...
}(Array.prototype.slice));
Use [].slice
:
function someFunction() {
var args = [].slice.call(arguments);
}
Create your own slice (you tried this but had an error in the arguments):
function slice(arr) {
return Array.prototype.slice.call(arr);
}
function someFunction() {
var args = slice(arguments);
}
Use the modern Array.from
(be sure to polyfill for backwards compatibility):
function someFunction() {
var args = Array.from(arguments);
}
If you're in an environment where you can safely use the spread operator, then there is no need for any call to slice
:
function someFunction() {
var args = [...arguments];
}
Upvotes: 3
Reputation: 6476
There are numerous ways to use arguments
in a way that causes the function to be unoptimizable. One must be extremely careful when using arguments
.
From arguments object on MDN:
Important: You should not slice on arguments because it prevents optimizations in JavaScript engines (V8 for example). Instead, try constructing a new array by iterating through the arguments object.
As Node.js uses V8 you probably want to do something like this:
function parseArgs() {
var args = new Array(arguments.length);
for (var i = 0; i < arguments.length; ++i) {
args[i] = arguments[i];
}
return args;
}
function myFunc() {
var args = parseArgs.apply(null, arguments);
console.log(args); // => [1,2,3]
}
myFunc(1, 2, 3);
Upvotes: 1
Reputation: 14423
If you don't want to write Array.prototype.slice.call(args)
everytime you can do:
var slice = Function.call.bind(Array.prototype.slice);
And then you can use it anywhere like:
function fn(){
var arr = slice(arguments);
}
Upvotes: 5
Reputation: 239463
You need to pass the arguments object of foo
and slice only that, like this
function parseArgs(args) {
return Array.prototype.slice.call(args);
}
When you use arguments
inside parseArgs
it will refer to the arguments received by that function only not the one which foo
received.
In ECMA Script 2015, you can use Array.from
on arguments
object directly, like this
function foo() {
console.log(Array.from(arguments));
}
Alternatively, you can keep the parseArgs
as it is and spread the arguments
over parseArgs
in ECMA Script 2015, like this
function parseArgs() {
return Array.prototype.slice.call(arguments);
}
function foo() {
console.log(parseArgs(...arguments));
}
This basically means that you are spreading the arguments
received by foo
and passing them over to parseArgs
so that it will also receive the same arguments.
Upvotes: 2
Reputation: 71901
What about:
var parseArgs = function(args) {
return Array.prototype.slice.call(args)
}
var foo = function() {
console.log(parseArgs(arguments))
}
foo('one', 'two', 'three')
This way you parse the actual arguments array
Upvotes: 1