JavaScript中的arguments
对象是一个奇怪的疣 - 它在大多数情况下就像一个数组,但它不是实际上一个数组对象。由于它是really something else entirely,因此forEach
,sort
,filter
和map
等Array.prototype
没有有用的功能。
使用简单的for循环从arguments对象构造一个新数组非常容易。例如,此函数对其参数进行排序:
function sortArgs() {
var args = [];
for (var i = 0; i < arguments.length; i++)
args[i] = arguments[i];
return args.sort();
}
但是,这是一个相当可怜的事情,只需要访问非常有用的JavaScript数组函数。是否有使用标准库的内置方法?
答案 0 :(得分:684)
如果您能够使用ES6,您可以使用:
<强> Rest Parameters 强>
function sortArgs(...args) {
return args.sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();
您可以阅读link
rest参数语法允许我们将无限数量的参数表示为数组。
如果您对...
语法感到好奇,则会将其称为 Spread Operator ,您可以阅读更多here。
使用 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
只需将类似Array或Iterable的对象转换为Array实例。
您实际上只需在参数对象上使用Array
的{{3}}函数,它就会将其转换为标准的JavaScript数组。您只需通过Array的原型手动引用它:
function sortArgs() {
var args = Array.prototype.slice.call(arguments);
return args.sort();
}
为什么这样做?好吧,这是摘自slice
:
注意:
slice
函数是故意通用的;它不要求 this 值为Array对象。因此,它可以转移到其他类型的对象以用作方法。slice
函数是否可以成功应用于宿主对象是依赖于实现的。
因此,slice
适用于具有length
属性的任何内容,arguments
可以方便地执行此操作。
如果Array.prototype.slice
对你来说太过,,你可以使用数组文字略微缩写:
var args = [].slice.call(arguments);
但是,我倾向于认为前一版本更明确,所以我更喜欢它。滥用数组文字符号感觉很乱,看起来很奇怪。
答案 1 :(得分:38)
还值得引用this Bluebird promises library wiki page,它展示了如何将arguments
对象管理到数组中,使得函数在V8 JavaScript引擎下可以优化:
function doesntLeakArguments() {
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}
return args;
}
此方法用于支持var args = [].slice.call(arguments);
。作者还展示了构建步骤如何帮助减少冗长。
答案 2 :(得分:28)
function sortArgs(){ return [].slice.call(arguments).sort() }
// Returns the arguments object itself
function sortArgs(){ return [].sort.call(arguments) }
有意使一些数组方法不要求目标对象是实际数组。它们只要求目标具有名为 length 的属性和索引(必须为零或更大的整数)。
[].sort.call({0:1, 1:0, length:2}) // => ({0:0, 1:1, length:2})
答案 3 :(得分:12)
使用:
function sortArguments() {
return arguments.length === 1 ? [arguments[0]] :
Array.apply(null, arguments).sort();
}
Array(arg1, arg2, ...)
返回[arg1, arg2, ...]
Array(str1)
返回[str1]
Array(num1)
返回一个包含num1
元素的数组
你必须检查参数的数量!
Array.slice
版本(较慢):
function sortArguments() {
return Array.prototype.slice.call(arguments).sort();
}
Array.push
版本(比切片更慢,更快):
function sortArguments() {
var args = [];
Array.prototype.push.apply(args, arguments);
return args.sort();
}
移动版本(速度较慢,但体积较小):
function sortArguments() {
var args = [];
for (var i = 0; i < arguments.length; ++i)
args[i] = arguments[i];
return args.sort();
}
Array.concat
版本(最慢):
function sortArguments() {
return Array.prototype.concat.apply([], arguments).sort();
}
答案 4 :(得分:9)
如果您正在使用jQuery,我认为以下内容更容易记住:
function sortArgs(){
return $.makeArray(arguments).sort();
}
答案 5 :(得分:5)
Here is benchmark将几个参数转换为数组的方法。
就我而言,少量争论的最佳解决方案是:
function sortArgs (){
var q = [];
for (var k = 0, l = arguments.length; k < l; k++){
q[k] = arguments[k];
}
return q.sort();
}
对于其他情况:
function sortArgs (){ return Array.apply(null, arguments).sort(); }
答案 6 :(得分:5)
在ECMAScript 6中,不需要像Array.prototype.slice()
那样使用丑陋的黑客攻击。您可以使用spread syntax (...
)。
(function() {
console.log([...arguments]);
}(1, 2, 3))
它可能看起来很奇怪,但它相当简单。它只提取arguments
'元素并将它们放回到数组中。如果您仍然不明白,请参阅以下示例:
console.log([1, ...[2, 3], 4]);
console.log([...[1, 2, 3]]);
console.log([...[...[...[1]]]]);
请注意,它在IE 11等旧版浏览器中不起作用,因此如果您想支持这些浏览器,则应使用Babel。
答案 7 :(得分:4)
我建议使用ECMAScript 6 dateFromString
,它会将尾随参数绑定到数组。使用此解决方案,您无需触摸arguments
对象,您的代码将被简化。这个解决方案的缺点是它不适用于大多数浏览器,所以你必须使用像Babel这样的JS编译器。在引擎盖下,Babel将arguments
转换为带有for循环的数组。
function sortArgs(...args) {
return args.sort();
}
如果您不能使用ECMAScript 6,我建议您查看其他一些答案,例如@Jonathan Fingland
function sortArgs() {
var args = Array.prototype.slice.call(arguments);
return args.sort();
}
答案 8 :(得分:4)
Lodash:
var args = _.toArray(arguments);
行动中:
(function(){ console.log(_.toArray(arguments).splice(1)); })(1, 2, 3)
产生
[2,3]
答案 9 :(得分:4)
使用Array.from()
,它将类似数组的对象(例如arguments
)作为参数并将其转换为数组:
(function() {
console.log(Array.from(arguments));
}(1, 2, 3));
请注意,它在IE 11等旧版浏览器中不起作用,因此如果您想支持这些浏览器,则应使用Babel。
答案 10 :(得分:3)
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));
答案 11 :(得分:1)
另一个答案。
使用黑魔法术:
function sortArguments() {
arguments.__proto__ = Array.prototype;
return arguments.slice().sort();
}
Firefox,Chrome,Node.js,IE11都可以。
答案 12 :(得分:1)
说明:将prototype
的{{1}}设置为arguments
Array.prototype
说明:获取function toArray() {
return Object.setPrototypeOf(arguments, Array.prototype)
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
的每个索引,将项放入数组的相应索引处的数组中。
arguments
说明:获取function toArray() {
return [].map.call(arguments, (_,k,a) => a[k])
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
的每个索引,将项放入数组的相应索引处的数组中。
for..of
循环
arguments
说明:创建对象,将对象的属性设置为每个索引function toArray() {
let arr = []; for (let prop of arguments) arr.push(prop); return arr
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
的项目;将创建的对象的arguments
设置为prototype
Array.prototype
答案 13 :(得分:0)
Benshmarck 3方法:
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);
RESULT?
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
享受!
答案 14 :(得分:0)
function sortArgs(...args) {
return args.sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(1, 2, 3, 4).toString();
答案 15 :(得分:0)
虽然其他参数运行良好,但如果您出于某种原因想继续使用arguments
,请考虑
function sortArgs() {
return [...arguments].sort()
}
[...arguments]
可以被视为Array.from(arguments)
的替代品,它也非常有效。
ES7替代方案是数组理解:
[for (i of arguments) i].sort()
如果您想在排序之前处理或过滤参数,这可能是最简单的:
[for (i of arguments) if (i % 2) Math.log(i)].sort()
答案 16 :(得分:0)
function x(){
var rest = [...arguments]; console.log(rest);return
rest.constructor;
};
x(1,2,3)
我尝试过简单的破坏技术
答案 17 :(得分:0)
Arguments对象仅在函数体内可用。虽然您可以像对象一样索引Arguments对象,但它不是数组。除了length之外,它没有任何数组属性。
// 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();
虽然它可以像数组一样编入索引,如本例所示:
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));
但是,Arguments对象不是数组,除了length之外没有任何其他属性。
您可以将arguments对象转换为数组,此时您可以访问Arguments对象。
您可以通过多种方式访问函数体内的arguments对象,其中包括:
Array.prototype.slice.call(arguments)
function giveMeArgs(arg1,arg2){
var args = Array.prototype.slice.call(arguments);
return args
}
console.log( giveMeArgs(1,2));
[]。slice.call(参数)。
function giveMeArgs(arg1,arg2){
var args = [].slice.call(arguments);
return args;
}
console.log( giveMeArgs(1,2) );
function giveMeArgs(...args){
return args;
}
console.log(giveMeArgs(1,2))
function giveMeArgs(){
var args = [...arguments];
return args;
}
console.log(giveMeArgs(1,2));
function giveMeArgs(){
var args = Array.from(arguments);
return args;
}
console.log(giveMeArgs(1,2));
答案 18 :(得分:0)
你可以用任何参数创建一个可重用的函数,最简单的就是这样:
function sortArgs() {
return [...arguments].sort();
}
sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];
Spread语法可用于 ES6 及以上...
但是,如果您想使用与 ES5 及以下版本兼容的内容,则可以使用Array.prototype.slice.call
,因此您的代码如下所示:
function sortArgs() {
return Array.prototype.slice.call(arguments).sort();
}
sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];
还有其他一些方法可以做到这一点,例如使用Array.from
或循环参数并将它们分配给新数组......
答案 19 :(得分:0)
这是一个简洁明了的解决方案:
function argsToArray() {
return Object.values(arguments);
}
// example usage
console.log(
argsToArray(1, 2, 3, 4, 5)
.map(arg => arg*11)
);
Object.values( )
将以数组的形式返回对象的值,并且由于arguments
是对象,因此它将arguments
转换为数组,从而为您提供所有数组的辅助函数,例如map
,forEach
,filter
等。
答案 20 :(得分:-2)
这是一个非常古老的问题,但我认为我的解决方案比以前的解决方案更容易打字,并且不依赖于外部库:
function sortArguments() {
return Array.apply(null, arguments).sort();
}