Hur kan jag konvertera objektet "arguments" till en array i JavaScript?
Objektet arguments i JavaScript är en märklig buckla—det fungerar nästan som en array i de flesta situationer, men det är faktiskt inte ett arrayobjekt. Eftersom det egentligen är något helt annat, har det inte de användbara funktionerna från Array.prototype som forEach, sort, filter och map.
Det är extremt enkelt att skapa en ny array från ett arguments-objekt med en enkel for-loop. Till exempel sorterar denna funktion sina argument:
function sortArgs() {
var args = [];
for (var i = 0; i < arguments.length; i++)
args[i] = arguments[i];
return args.sort();
}
Men detta är en ganska ynklig sak att behöva göra bara för att få tillgång till de extremt användbara JavaScript-arrayfunktionerna. Finns det ett inbyggt sätt att göra det med standardbiblioteket?
Svar #1
ES6 använder restparametrar
Om du kan använda ES6 kan du använda:
Restparametrar
function sortArgs(...args) {
return args.sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();Som du kan läsa i länken
Restparameter-syntaxen låter oss representera ett obestämt antal argument som en array.
Om du är nyfiken på ...-syntaxen, kallas den Spread Operator och du kan läsa mer här.
ES6 använder Array.from()
Använder Array.from:
function sortArgs() {
return Array.from(arguments).sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();Array.from omvandlar helt enkelt Array-liknande eller Itererbara objekt till Array-instans.
ES5
Du kan faktiskt bara använda Array's slice-funktion på ett argumentsobjekt, och det kommer att konvertera det till en standard JavaScript-array. Du måste bara referera till det manuellt genom Arrays prototype:
function sortArgs() {
var args = Array.prototype.slice.call(arguments);
return args.sort();
}
Varför fungerar detta? Nå, här är ett utdrag från ECMAScript 5-dokumentationen själv:
OBS:
slice-funktionen är avsiktligt generisk; den kräver inte att dess this-värde är ett Array-objekt. Därför kan den överföras till andra typer av objekt för användning som en metod. Huruvidaslice-funktionen kan tillämpas framgångsrikt på ett värdobjekt beror på implementeringen.
Därför fungerar slice på allt som har en length-egenskap, vilket arguments praktiskt nog har.
Om Array.prototype.slice är för långt för dig, kan du förkorta det något genom att använda array-litteraler:
var args = [].slice.call(arguments);
Jag tenderar dock att känna att den tidigare versionen är mer uttrycklig, så jag skulle föredra den istället. Att missbruka array-litteralnotationen känns hackigt och ser konstigt ut.
Svar #2
Det är också värt att hänvisa till den här sidan på Bluebird promises library wiki som visar hur man hanterar arguments-objektet till en array på ett sätt som gör att funktionen kan optimeras under V8 JavaScript-motorn:
function doesntLeakArguments() {
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}
return args;
}
Denna metod används till fördel för var args=[].slice.call(arguments);. Författaren visar också hur ett byggsteg kan hjälpa till att minska ordflödet.
Svar #3
function sortArgs(){ return [].slice.call(arguments).sort() }
// Returns the arguments object itself
function sortArgs(){ return [].sort.call(arguments) }
Vissa arraymetoder är avsiktligt gjorda så att de inte kräver att målobjektet är en faktisk array. De kräver endast att målet har en egenskap som heter length och index (som måste vara noll eller större heltal).
[].sort.call({0:1, 1:0, length:2}) // => ({0:0, 1:1, length:2})
Svar #4
Använd :
function sortArguments() {
return arguments.length === 1 ? [arguments[0]] :
Array.apply(null, arguments).sort();
}
Array(arg1, arg2, ...) returnerar [arg1, arg2, ...]
Array(str1) returnerar [str1]
Array(num1) returnerar en array som har num1 element
Du måste kontrollera antalet argument!
Array.slice-version (långsammare):
function sortArguments() {
return Array.prototype.slice.call(arguments).sort();
}
Array.push-version (långsammare, snabbare än slice):
function sortArguments() {
var args = [];
Array.prototype.push.apply(args, arguments);
return args.sort();
}
Flytta version (långsammare, men liten storlek är snabbare):
function sortArguments() {
var args = [];
for (var i = 0; i < arguments.length; ++i)
args[i] = arguments[i];
return args.sort();
}
Array.concat-version (långsammaste):
function sortArguments() {
return Array.prototype.concat.apply([], arguments).sort();
}
