引言
JavaScript
函数具有像数组一样的对象,这些对象称为arguments
,与传递给函数的参数相对应。传递给JavaScript
函数的所有参数都可以使用arguments
对象来引用。
arguments是数组吗?
要回答这个问题首先了解一下argument
的具体知识。
函数中的arguments对象
语法: arguments
描述
arguments
对象是所有函数(非箭头)中都可用的局部变量。可以使用arguments
对象在函数中引用函数的参数。此对象包含传递给函数的每个参数的条目,第一个条目的索引从0开始。
argument[0];
argument[1];
也可以设置其参数:
arguments[1]='new value';
事实上,arguments
对象不是一个Array
。类似于一个数组,但是除了length属性和索引元素之外没有任何Array
属性。
何时调用arguments?
如果调用的参数多于正式声明接受的参数,则可以使用arguments
对象。这种技术对于可以传递可变数量的参数的函数很有用。使用 arguments.length
来确定传递给函数参数的个数,然后使用arguments
对象来处理每个参数。
属性
arguments.callee
:指向当前执行的函数。
arguments.caller
:指向调用当前函数的函数。
arguments.length
:指向传递给当前函数的参数数量。
arguments[@@iterator]
:返回一个新的Array迭代器对象,该对象包含参数中每个索引的值。
注意: 现在在严格模式下,arguments对象已与过往不同。arguments[@@iterator]不再与函数的实际形参之间共享,同时caller属性也被移除。
例子
遍历参数求和
function add(){
var sum=0;
var len=arguments.length;
for(var i=0;i<len;i++){
sum+=arguments[i];
}
return sum;
}
add(); //-> 0
add(1); //-> 1
add(1,2,3,4); //-> 10
定义连接字符串的函数
这个例子定义了一个函数来连接字符串。这个函数唯一正式声明了的参数是一个字符串,该参数指定一个字符作为衔接点来连接字符串。该函数定义如下:
function myConcat(separator){
var args=Array.prototype.slice.call(arguments,1);
return args.join(separator);
}
myConcat(",","red","orange","blue"); //-> "red,orange,blue"
myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); //-> "elephant; giraffe; lion; cheetah"
综上,arguments不是一个数组,而是一个类数组。
类数组及转换成数组的方法
什么是类数组?
类数组,顾名思义,类似于一个数组,但是它是一个对象:是相当于一个对象,里面有数组的值以及相应的属性-length。
- 拥有length属性,其属性(索引)为非负整数
- 不具有数组所具有的方法
var likeArray={
0:"a",
1:"第二"
2:"3"
'length':3, //重点在这!没有length属性就不是类数组。
splice:Array.prototype.slice,
splice:Array.prototype.splice
}
likeArray.push(2); //虽然此时likeArray因为splice方法将{}变成了[],并且有length属性
//但是其继承的原型还是Object,还不能调用push(),会报错!
JS中常见类数组对象
NameNodeMap
Dom
元素用过attributes
属性获取NameNodeMap
对象:
var div=document.getElementById('div'); var nameNodeMap=div.attribute;
这是NameNodeMap的结构:
HTMLCollection 通过
DOM
元素的children
属性获取元素的子元素集合,即HTMLCollection
集合对象
NodeList 通过
DOM
元素的childNodes
属性返回包含被选节点的子节点的NodeList
类数组转换成数组的方法
Array.prototype.slice.call(likeArray)
: 利用slice的返回新数组以及call改变this指向而形成一个新数组Array.from(likeArray)
:ES6的新方法[...likeArray]
,或者在函数传值时用..."收集"; //...要求likeArray是有Symbol的iterator属性
var obj = {
'a':1,
'length':5,
},
//方法一:
arr = Array.prototype.slice.call(obj), //-> [empty * 5]
//方法二:
arr1 = Array.from(obj); //-> [undefined,undefined,undefined,undefined,undefined]
//方法三(ES6展开运算符):
var arr2=[...obj] //报错,因为obj无Symbol的iterator属性
var set = new Set([1,2,3]); //set有Symbol的iterator属性
console.log([...set]); //[1,2,3]
//方法四(利用concat):
function sum(a, b) {
let args = Array.prototype.concat.apply([], arguments);//apply方法会把第二个参数展开
console.log(args.reduce((sum, cur) => sum + cur));//args可以调用数组原生的方法啦
}
sum(1, 2);//3