首页 web前端 js教程 JavaScript arguments对象全面介绍

JavaScript arguments对象全面介绍

Oct 13, 2016 am 09:10 AM

1. 什么是 arguments

MDN 上解释:

arguments 是一个类数组对象。代表传给一个function的参数列表。

我们先用一个例子直观了解下 JavaScript 中的 arguments 长什么样子。

function printArgs() { 
 
console.log(arguments); 
 
} 
 
printArgs("A", "a", 0, { foo: "Hello, arguments" });
登录后复制

执行结果是:

["A", "a", 0, Object]
登录后复制

乍一看,结果是个数组,但并不是真正的数组,所以说 arguments 是一个类数组的对象(想了解真正数组与类数组对象的区别可以一直翻到最后)。

再看看 arguments 表示的内容,其表示了函数执行时传入函数的所有参数。在上面的例子中,代表了传入 printArgs 函数中的四个参数,可以分别用 arguments[0]、 arguments[1]... 来获取单个的参数。

2. arguments 操作

2.1 arguments length

arguments 是个类数组对象,其包含一个 length 属性,可以用 arguments.length 来获得传入函数的参数个数。

function func() { 
 
console.log("The number of parameters is " + arguments.length); 
 
} 
 
func(); 
 
func(1, 2); 
 
func(1, 2, 3);
登录后复制

执行结果如下:

The number of parameters is 0 
 
The number of parameters is 2 
 
The number of parameters is 3
登录后复制

2.2 arguments 转数组

通常使用下面的方法来将 arguments 转换成数组:

Array.prototype.slice.call(arguments);
登录后复制

还有一个更简短的写法:

[].slice.call(arguments);
登录后复制

在这里,只是简单地调用了空数组的 slice 方法,而没有从 Array 的原型层面调用。

为什么上面两种方法可以转换呢?

首先,slice 方法得到的结果是一个数组,参数便是 arguments。事实上,满足一定条件的对象都能被 slice 方法转换成数组。看个例子:

const obj = { 0: "A", 1: "B", length: 2 }; 
 
const result = [].slice.call(obj); 
 
console.log(Array.isArray(result), result);
登录后复制

执行结果是:

true ["A", "B"]
登录后复制

从上面例子可以看出,条件就是: 1) 属性为 0,1,2...;2) 具有 length 属性;

另外,有一个需要注意的地方就是,不能将函数的 arguments 泄露或者传递出去。什么意思呢?看下面的几个泄露 arguments 的例子:

// Leaking arguments example1: 
 
function getArgs() { 
 
    return arguments; 
 
} 
 
// Leaking arguments example2: 
 
function getArgs() { 
 
    const args = [].slice.call(arguments); 
 
    return args; 
 
} 
 
// Leaking arguments example3: 
 
function getArgs() { 
 
    const args = arguments; 
 
    return function() { 
 
    return args; 
 
    }; 
 
}
登录后复制

上面的做法就直接将函数的 arguments 对象泄露出去了,最终的结果就是 V8 引擎将会跳过优化,导致相当大的性能损失。

你可以这么做:

function getArgs() { 
 
    const args = new Array(arguments.length); 
 
    for(let i = 0; i < args.length; ++i) { 
 
    args[i] = arguments[i]; 
 
    } 
 
    return args; 
 
}
登录后复制

那就很好奇了,我们每次使用 arguments 时通常第一步都会将其转换为数组,同时 arguments 使用不当还容易导致性能损失,那么为什么不将 arguments 直接设计成数组对象呢?

这需要从这门语言的一开始说起。arguments 在语言的早期就引入了,当时的 Array 对象具有 4 个方法: toString、 join、 reverse 和 sort。arguments 继承于 Object 的很大原因是不需要这四个方法。而现在,Array 添加了很多强大的方法,比如 forEach、map、filter 等等。那为什么现在不在新的版本里让 arguments 重新继承自 Array呢?其实 ES5 的草案中就包含这一点,但为了向前兼容,最终还是被委员会否决了。

2.3 修改 arguments 值

在严格模式与非严格模式下,修改函数参数值表现的结果不一样。看下面的两个例子:

function foo(a) { 
 
"use strict"; 
 
console.log(a, arguments[0]); 
 
a = 10; 
 
console.log(a, arguments[0]); 
 
arguments[0] = 20; 
 
console.log(a, arguments[0]); 
 
} 
 
foo(1);
登录后复制

输出:

1 1 
 
10 1 
 
10 20
登录后复制

另一个非严格模式的例子:

function foo(a) { 
 
console.log(a, arguments[0]); 
 
a = 10; 
 
console.log(a, arguments[0]); 
 
arguments[0] = 20; 
 
console.log(a, arguments[0]); 
 
} 
 
foo(1);
登录后复制

输出结果为:

1 1 
 
10 10 
 
20 20
登录后复制

从上面的两个例子中可以看出,在严格模式下,函数中的参数与 arguments 对象没有联系,修改一个值不会改变另一个值。而在非严格模式下,两个会互相影响。

2.4 将参数从一个函数传递到另一个函数

下面是将参数从一个函数传递到另一个函数的推荐做法。

function foo() { 
 
bar.apply(this, arguments); 
 
} 
 
function bar(a, b, c) { 
 
// logic 
 
}
登录后复制

2.5 arguments 与重载

很多语言中都有重载,但 JavaScript 中没有。先看个例子:

function add(num1, num2) { 
 
console.log("Method one"); 
 
return num1 + num2; 
 
} 
 
function add(num1, num2, num3) { 
 
console.log("Method two"); 
 
return num1 + num2 + num3; 
 
} 
 
add(1, 2); 
 
add(1, 2, 3);
登录后复制

执行结果为:

Method two 
 
Method two
登录后复制

所以,JavaScript 中,函数并没有根据参数的不同而产生不同的调用。

是不是 JavaScript 中就没有重载了呢?并不是,我们可以利用 arguments 模拟重载。还是上面的例子。

function add(num1, num2, num3) { 
 
    if (arguments.length === 2) { 
 
    console.log("Result is " + (num1 + num2)); 
 
    } 
 
    else if (arguments.length === 3) { 
 
    console.log("Result is " + (num1 + num2 + num3)); 
 
    } 
 
} 
 
add(1, 2); 
 
add(1, 2, 3)
登录后复制

执行结果如下:

Result is 3 
 
Result is 6
登录后复制

3. ES6 中的 arguments

3.1 扩展操作符

直接上栗子:

function func() { 
 
console.log(...arguments); 
 
} 
 
func(1, 2, 3);
登录后复制

执行结果是:

1 2 3
登录后复制

简洁地讲,扩展操作符可以将 arguments 展开成独立的参数。

3.2 Rest 参数

还是上栗子:

function func(firstArg, ...restArgs) { 
 
console.log(Array.isArray(restArgs)); 
 
console.log(firstArg, restArgs); 
 
} 
 
func(1, 2, 3);
登录后复制

执行结果是:

true 
 
1 [2, 3]
登录后复制

从上面的结果可以看出,Rest 参数表示除了明确指定剩下的参数集合,类型是 Array。

3.3 默认参数

栗子:

function func(firstArg = 0, secondArg = 1) { 
 
console.log(arguments[0], arguments[1]); 
 
console.log(firstArg, secondArg); 
 
} 
 
func(99);
登录后复制

执行结果是:

99 undefined 
 
99 1
登录后复制

可见,默认参数对 arguments 没有影响,arguments 还是仅仅表示调用函数时所传入的所有参数。

3.4 arguments 转数组

Array.from() 是个非常推荐的方法,其可以将所有类数组对象转换成数组。

4. 数组与类数组对象

数组具有一个基本特征:索引。这是一般对象所没有的。

const obj = { 0: "a", 1: "b" }; 
 
const arr = [ "a", "b" ];
登录后复制

我们利用 obj[0]、arr[0] 都能取得自己想要的数据,但取得数据的方式确实不同的。obj[0] 是利用对象的键值对存取数据,而arr[0] 却是利用数组的索引。事实上,Object 与 Array 的唯一区别就是 Object 的属性是 string,而 Array 的索引是 number。

下面看看类数组对象。

伪数组的特性就是长得像数组,包含一组数据以及拥有一个 length 属性,但是没有任何 Array 的方法。再具体的说,length 属性是个非负整数,上限是 JavaScript 中能精确表达的最大数字;另外,类数组对象的 length 值无法自动改变。

如何自己创建一个类数组对象?

function Foo() {} 
 
Foo.prototype = Object.create(Array.prototype); 
 
const foo = new Foo(); 
 
foo.push(&#39;A&#39;); 
 
console.log(foo, foo.length); 
 
console.log("foo is an array? " + Array.isArray(foo));
登录后复制

执行结果是:

["A"] 1 
 
foo is an array? false
登录后复制

也就是说 Foo 的示例拥有 Array 的所有方法,但类型不是 Array。

如果不需要 Array 的所有方法,只需要部分怎么办呢?

function Bar() {} 
 
Bar.prototype.push = Array.prototype.push; 
 
const bar = new Bar(); 
 
bar.push(&#39;A&#39;); 
 
bar.push(&#39;B&#39;); 
 
console.log(bar);
登录后复制

执行结果是:

Bar {0: "A", 1: "B", length: 2}
登录后复制

参考:

JavaScript中的数组与伪数组的区别

MDN arguments

Avoid modifying or passing arguments into other functions — it kills optimization

Optimization killers

Why isn't a function's arguments object an array in Javascript?

arguments 对象

Advanced Javascript: Objects, Arrays, and Array-Like objects

JavaScript 特殊对象 Array-Like Objects 详解

What is a good way create a Javascript array-like object?


本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

在JavaScript中替换字符串字符 在JavaScript中替换字符串字符 Mar 11, 2025 am 12:07 AM

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

如何创建和发布自己的JavaScript库? 如何创建和发布自己的JavaScript库? Mar 18, 2025 pm 03:12 PM

文章讨论了创建,发布和维护JavaScript库,专注于计划,开发,测试,文档和促销策略。

如何在浏览器中优化JavaScript代码以进行性能? 如何在浏览器中优化JavaScript代码以进行性能? Mar 18, 2025 pm 03:14 PM

本文讨论了在浏览器中优化JavaScript性能的策略,重点是减少执行时间并最大程度地减少对页面负载速度的影响。

前端热敏纸小票打印遇到乱码问题怎么办? 前端热敏纸小票打印遇到乱码问题怎么办? Apr 04, 2025 pm 02:42 PM

前端热敏纸小票打印的常见问题与解决方案在前端开发中,小票打印是一个常见的需求。然而,很多开发者在实...

如何使用浏览器开发人员工具有效调试JavaScript代码? 如何使用浏览器开发人员工具有效调试JavaScript代码? Mar 18, 2025 pm 03:16 PM

本文讨论了使用浏览器开发人员工具的有效JavaScript调试,专注于设置断点,使用控制台和分析性能。

立即提高jQuery性能的10种方法 立即提高jQuery性能的10种方法 Mar 11, 2025 am 12:15 AM

本文概述了十个简单的步骤,可以显着提高脚本的性能。 这些技术很简单,适用于所有技能水平。 保持更新:使用bundler(例如vite)的npm等软件包经理来确保

使用Passport与semelize和MySQL 使用Passport与semelize和MySQL Mar 11, 2025 am 11:04 AM

续集是一个基于承诺的node.js orm。它可以与PostgreSQL,MySQL,MariadB,Sqlite和MSSQL一起使用。在本教程中,我们将为Web应用程序的用户实施身份验证。我们将使用Passport,Passport,Midderw的流行身份验证

如何构建简单的jQuery滑块 如何构建简单的jQuery滑块 Mar 11, 2025 am 12:19 AM

本文将引导您使用jQuery库创建一个简单的图片轮播。我们将使用bxSlider库,它基于jQuery构建,并提供许多配置选项来设置轮播。 如今,图片轮播已成为网站必备功能——一图胜千言! 决定使用图片轮播后,下一个问题是如何创建它。首先,您需要收集高质量、高分辨率的图片。 接下来,您需要使用HTML和一些JavaScript代码来创建图片轮播。网络上有很多库可以帮助您以不同的方式创建轮播。我们将使用开源的bxSlider库。 bxSlider库支持响应式设计,因此使用此库构建的轮播可以适应任何

See all articles