Como posso converter o objeto de “argumentos” para uma matriz em JavaScript?
-
12-09-2019 - |
Pergunta
O objeto arguments
em JavaScript é um estranho verruga-age apenas como um array na maioria das situações, mas não é realmente um objeto array. Desde que é realmente algo completamente diferente , ele doesn 't têm as funções úteis a partir Array.prototype
como forEach
, sort
, filter
e map
.
É tão fácil de construir uma nova matriz de um objeto argumentos com um loop for simples. Por exemplo, esta função ordena seus argumentos:
function sortArgs() {
var args = [];
for (var i = 0; i < arguments.length; i++)
args[i] = arguments[i];
return args.sort();
}
No entanto, isso é uma coisa bastante lamentável ter que fazer simplesmente para obter acesso às funções extremamente úteis de matrizes de JavaScript. Existe um built-in maneira de fazê-lo usando a biblioteca padrão?
Solução
ES6 usando parâmetros de descanso
Se você é capaz de usar ES6 você pode usar:
function sortArgs(...args) {
return args.sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();
Como você pode ler no ligação
A sintaxe parâmetro resto nos permite representar um número indefinido de argumentos como uma matriz.
Se você está curioso sobre a sintaxe ...
, ele é chamado Espalhe Operador e você pode ler mais aqui .
ES6 usando Array.from ()
Usando 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
simplesmente converter array-like ou Iterable objetos em ocorrências de Array.
ES5
Você pode realmente usar apenas Array
do slice
função em um objeto de argumentos, e ele irá convertê-lo em uma matriz JavaScript padrão. Você só vai ter que fazer referência a ela manualmente através protótipo da matriz:
function sortArgs() {
var args = Array.prototype.slice.call(arguments);
return args.sort();
}
Por que isso funciona? Bem, aqui está um trecho da ECMAScript 5 própria documentação :
NOTA : A função
slice
é intencionalmente genérico; ele não exige que a sua este valor ser um objeto Array. Por isso, pode ser transferida para outros tipos de objetos para uso como um método. Se a funçãoslice
pode ser aplicado com sucesso em um objeto de host é dependente de implementação.
Portanto, slice
funciona em qualquer coisa que tenha uma propriedade length
, que arguments
convenientemente faz.
Se Array.prototype.slice
é muito de um bocado para você, você pode abreviar-o ligeiramente usando literais de matriz:
var args = [].slice.call(arguments);
No entanto, eu tendem a sentir que a versão anterior é mais explícito, então eu prefiro que em seu lugar. Abusando da matriz notação literal sente hacky e olhares estranhos.
Outras dicas
Também vale a pena referência este Bluebird promete página wiki biblioteca que mostra como para gerenciar o objeto arguments
em conjunto de uma forma que faz a função otimizável em motor V8 JavaScript :
function doesntLeakArguments() {
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}
return args;
}
Este método é usado em favor de var args = [].slice.call(arguments);
. O autor também mostra como uma etapa de compilação pode ajudar a reduzir a verbosidade.
function sortArgs(){ return [].slice.call(arguments).sort() }
// Returns the arguments object itself
function sortArgs(){ return [].sort.call(arguments) }
Alguns métodos de matriz são intencionalmente feitos para não exigir o objecto alvo a ser uma matriz real. Eles só exigem a meta de ter uma propriedade chamada comprimento e índices (que deve ser zero ou maiores números inteiros).
[].sort.call({0:1, 1:0, length:2}) // => ({0:0, 1:1, length:2})
Use:
function sortArguments() {
return arguments.length === 1 ? [arguments[0]] :
Array.apply(null, arguments).sort();
}
Array(arg1, arg2, ...)
retornos [arg1, arg2, ...]
Array(str1)
retornos [str1]
Array(num1)
retorna uma matriz que tem elementos num1
Você deve verificar o número de argumentos!
Versão Array.slice
(mais lento):
function sortArguments() {
return Array.prototype.slice.call(arguments).sort();
}
Versão Array.push
(mais lento, mais rápido do que fatia):
function sortArguments() {
var args = [];
Array.prototype.push.apply(args, arguments);
return args.sort();
}
Versão Move (mais lento, mas o tamanho pequeno é mais rápido):
function sortArguments() {
var args = [];
for (var i = 0; i < arguments.length; ++i)
args[i] = arguments[i];
return args.sort();
}
Versão Array.concat
(mais lento):
function sortArguments() {
return Array.prototype.concat.apply([], arguments).sort();
}
Se você estiver usando jQuery, o seguinte é um bom negócio mais fácil de lembrar na minha opinião:
function sortArgs(){
return $.makeArray(arguments).sort();
}
Em ECMAScript 6 não há necessidade de usar hacks feios como Array.prototype.slice()
. em vez disso você pode usar sintaxe spread (...
) .
(function() {
console.log([...arguments]);
}(1, 2, 3))
Pode parecer estranho, mas é bastante simples. Ele só extrai elementos arguments
' e colocá-los de volta para a matriz. Se você ainda não entendo, veja este exemplo:
console.log([1, ...[2, 3], 4]);
console.log([...[1, 2, 3]]);
console.log([...[...[...[1]]]]);
Note que ele não funciona em alguns navegadores mais antigos como o IE 11, então se você quiser para apoiar estes navegadores, você deve usar Babel .
Aqui é referência de vários métodos de conversão argumentos em array.
Quanto a mim, a melhor solução para pequena quantidade de argumentos é:
function sortArgs (){
var q = [];
for (var k = 0, l = arguments.length; k < l; k++){
q[k] = arguments[k];
}
return q.sort();
}
Para outros casos:
function sortArgs (){ return Array.apply(null, arguments).sort(); }
Eu recomendo usar ECMAScript 6 operador de propagação , que se ligará de arrasto parâmetros para uma matriz. Com esta solução você não precisa tocar o objeto arguments
e seu código será simplificado. A desvantagem desta solução é que ele não funciona na maioria dos navegadores, então em vez disso você terá que usar um compilador JS tais como Babel. Sob o capô Babel transformações arguments
para uma matriz com um loop.
function sortArgs(...args) {
return args.sort();
}
Se você não pode usar um ECMAScript 6, eu recomendo a olhar para algumas das outras respostas tais como @ Jonathan Fingland
function sortArgs() {
var args = Array.prototype.slice.call(arguments);
return args.sort();
}
Lodash:
var args = _.toArray(arguments);
em ação:
(function(){ console.log(_.toArray(arguments).splice(1)); })(1, 2, 3)
produz:
[2,3]
Use Array.from()
, que leva uma matriz semelhante objecto (tal como arguments
) como argumento e converte-a de matriz:
(function() {
console.log(Array.from(arguments));
}(1, 2, 3));
Note que ele não funciona em alguns navegadores mais antigos como o IE 11, então se você quiser para apoiar estes navegadores, você deve usar Babel .
function sortArg(){
var args = Array.from(arguments); return args.sort();
}
function sortArg(){
var args = Array.from(arguments);
return args.sort();
}
console.log(sortArg('a', 'b', 1, 2, '34', 88, 20, '19', 39, 'd', 'z', 'ak', 'bu', 90));
Outra resposta.
Períodos Use Black Magic:
function sortArguments() {
arguments.__proto__ = Array.prototype;
return arguments.slice().sort();
}
O Firefox, Chrome, Node.js, IE11 estão OK.
Tente usar Object.setPrototypeOf()
Explicação: Set prototype
de arguments
para Array.prototype
function toArray() {
return Object.setPrototypeOf(arguments, Array.prototype)
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
Explicação: Tome cada índice de arguments
, produto lugar em uma matriz no índice de matriz correspondente
pode alternativamente usar Array.prototype.map()
function toArray() {
return [].map.call(arguments, (_,k,a) => a[k])
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
Explicação: Tome cada índice de arguments
, produto lugar em uma matriz no índice de matriz correspondente
for..of
circuito
function toArray() {
let arr = []; for (let prop of arguments) arr.push(prop); return arr
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
Explicação: Criar objeto, defina as propriedades do objeto para itens em cada índice de arguments
; conjunto prototype
de criado objeto para Array.prototype
function toArray() {
var obj = {};
for (var prop in arguments) {
obj[prop] = {
value: arguments[prop],
writable: true,
enumerable: true,
configurable: true
}
}
return Object.create(Array.prototype, obj);
}
console.log(toArray("abc", 123, {def: 456}, [0, [7, [14]]]))
Aqui está uma solução limpa e concisa:
function argsToArray() {
return Object.values(arguments);
}
// example usage
console.log(
argsToArray(1, 2, 3, 4, 5)
.map(arg => arg*11)
);
Object.values( )
voltará os valores de um objeto como uma matriz, e desde arguments
é um objeto, ele será essencialmente converter arguments
em uma matriz, proporcionando-lhe todas as funções auxiliares de uma matriz como map
, forEach
, filter
, etc.
Benshmarck 3 métodos:
function test()
{
console.log(arguments.length + ' Argument(s)');
var i = 0;
var loop = 1000000;
var t = Date.now();
while(i < loop)
{
Array.prototype.slice.call(arguments, 0);
i++;
}
console.log(Date.now() - t);
i = 0,
t = Date.now();
while(i < loop)
{
Array.apply(null, arguments);
i++;
}
console.log(Date.now() - t);
i = 0,
t = Date.now();
while(i < loop)
{
arguments.length == 1 ? [arguments[0]] : Array.apply(null, arguments);
i++;
}
console.log(Date.now() - t);
}
test();
test(42);
test(42, 44);
test(42, 44, 88, 64, 10, 64, 700, 15615156, 4654, 9);
test(42, 'truc', 44, '47', 454, 88, 64, '@ehuehe', 10, 64, 700, 15615156, 4654, 9,97,4,94,56,8,456,156,1,456,867,5,152489,74,5,48479,89,897,894,894,8989,489,489,4,489,488989,498498);
RESULTADO?
0 Argument(s)
256
329
332
1 Argument(s)
307
418
4
2 Argument(s)
375
364
367
10 Argument(s)
962
601
604
40 Argument(s)
3095
1264
1260
Aproveite!
function sortArgs(...args) {
return args.sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(1, 2, 3, 4).toString();
Embora os parâmetros de descanso funcionar bem, se você quiser continuar a usar arguments
por alguma razão, considere
function sortArgs() {
return [...arguments].sort()
}
[...arguments]
pode ser considerado uma espécie de alternativa para Array.from(arguments)
, que também funciona perfeitamente bem.
Um ES7 alternativa é uma compreensão array:
[for (i of arguments) i].sort()
Esta poderia ser mais fácil se você quiser processo ou filtrar os argumentos antes da ordenação:
[for (i of arguments) if (i % 2) Math.log(i)].sort()
function x(){
var rest = [...arguments]; console.log(rest);return
rest.constructor;
};
x(1,2,3)
Eu tentei técnica destructing simples
O objeto Argumentos só está disponível dentro de um corpo função. Embora você possa índice objeto de argumentos como uma matriz, ela não é uma matriz. Ele não tem quaisquer outros do que o comprimento propriedades da matriz.
// function arguments length 5
function properties(a,b,c,d,e){
var function_name= arguments.callee.name
var arguments_length= arguments.length;
var properties_length= properties.length;
var function_from= properties.caller.name;
console.log('I am the function name: '+ function_name);
console.log('I am the function length, I am function spacific: '+ properties_length);
console.log('I am the arguments length, I am context/excution spacific: '+ arguments_length);
console.log('I am being called From: '+ function_from );
}
// arguments 3
function parent(){
properties(1,2,3);
}
//arguments length 3 because execution spacific
parent();
Embora possa ser indexado como um array como você pode ver neste exemplo:
function add(){
var sum=0;
for(var i=0; i< arguments.length;i++){
sum = sum + arguments[i];
}
return sum;
}
console.log(add(1,2,3));
No entanto, o objecto Argumentos não é uma matriz e não tem quaisquer outros do que o comprimento propriedades.
Você pode converter o objeto de argumentos em uma matriz em que ponto você pode acessar o objeto Arguments.
Há muitas maneiras que você pode acessar o objeto argumentos dentro de um corpo da função, e estes incluem:
- Você pode chamar o método Array.prototoype.slice.call.
Array.prototype.slice.call (argumentos)
function giveMeArgs(arg1,arg2){
var args = Array.prototype.slice.call(arguments);
return args
}
console.log( giveMeArgs(1,2));
- você pode usar a matriz literal
[]. Slice.call (argumentos).
function giveMeArgs(arg1,arg2){
var args = [].slice.call(arguments);
return args;
}
console.log( giveMeArgs(1,2) );
- você pode usar Resto ...
function giveMeArgs(...args){
return args;
}
console.log(giveMeArgs(1,2))
- você pode usar propagação [...]
function giveMeArgs(){
var args = [...arguments];
return args;
}
console.log(giveMeArgs(1,2));
- você pode usar Array.from ()
function giveMeArgs(){
var args = Array.from(arguments);
return args;
}
console.log(giveMeArgs(1,2));
Você pode criar uma função reutilizável para fazê-lo com quaisquer argumentos, o mais simples é algo como isto:
function sortArgs() {
return [...arguments].sort();
}
sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];
sintaxe Propagação pode ser usado em ES6 e acima ...
Mas se você gostaria de usar algo compatível com ES5 e abaixo, você pode usar Array.prototype.slice.call
, para que código se parece com isso:
function sortArgs() {
return Array.prototype.slice.call(arguments).sort();
}
sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];
Existem também algumas outras maneiras de fazer isso, por exemplo, usando Array.from
ou percorrer os argumentos e atribuí-los a uma nova matriz ...
Esta é uma questão muito antiga, mas eu acho que tenho uma solução que é ligeiramente mais fácil de escrever do que as soluções anteriores e não depende de bibliotecas externas:
function sortArguments() {
return Array.apply(null, arguments).sort();
}