再学JS--类数组对象与arguments

类数组对象

所谓的类数组对象:拥有一个length属性和若干索引属性的对象

var arr = ['name', 'age', 'sex']

var arrLike = {
    0: 'name',
    1: 'age',
    2: 'sex',
    length: 3
}

我们从读写、获取长度、遍历三个方面看看这两个对象。

读写

console.log(arr[0])  // name
console.log(arrLike[0])  // name

arr[0] = 'new name'
arrLike[0] = 'new name'

长度

console.log(arr.length)  // 3
console.log(arrLike.length)  // 3

遍历

for(var i = 0, len = arr.length; i<len; i++) {
    console.log(arr[i])
    // name age sex
}

for(var i = 0, len = arrLike.length; i<len; i++) {
    console.log(arr[i])
    // name age sex
}

调用数组方法

类数组可以调用数组的方法吗?

arrLike.push('city')
// arrLike is not a function

类数组无法直接调用数组方法,我们可以用Function.call间接调用

console.log(Array.prototype.join.call(arrLike, '&'))  // name&age&sex
console.log(Array.prototype.slice.call(arrLike)) // ['name','age','sex']
// slice可以做到类数组转数组
console.log(Array.prototype.map.call(arrLike, function(item){
    return item.toUpperCase()
}))  // ['NAME','AGE','SEX']

类数组转数组

上面的例子已经提到一种类数组转数组的方法,再补充完善下:

console.log(Array.prototype.slice.call(arrLike))
console.log(Array.prototype.splice.call(arrLike, 0))
// ES6
console.log(Array.from(arrLike))
console.log(Array.prototype.concat.apply([], arrLike))

Arguments对象

Arguments对象就是一个类数组对象,Arguments对象只定义在函数体内,包括了函数的参数和其他参数。在函数体中,arguments指代该函数的Arguments对象。

function foo(name, age, sex) {
    console.log(arguments)
}
foo('name', 'age', 'sex')

打印结果:

image-20200512095611667

我们看到除了类数组的索引属性和length属性之外,还有一个callee属性。

length属性

Arguments对象的length属性,表示实参的长度

function foo(name, age, sex) {
    // 实参长度
    console.log(arguments.length)  // 1
}
// 形参长度
console.log(foo.length)  // 3
foo('name')

callee属性

Arguments对象的callee属性,通过它可以调用函数自身。

通过下面闭包的例子来看下callee的解决方法:

var data = []
for(var i = 0; i < 3; i++) {
    (data[i] = function() {
        console.log(arguments.callee.i)
    }). i = i
}
console.log(data[0].i)  // 0
console.log(data[1].i)  // 1
console.log(data[2].i)  // 2

arguments和对象参数的绑定

function foo(name, age, sex, hobbit) {
    console.log(name, arguments[0])  // name, name
    // 改变形参
    arguments[0] = 'new name'
    console.log(name, arguments[0])  // new name, new name
    // 改变arguments
    arguments[1] = 'new age'
    console.log(name, arguments[1])  // new name, new age
    // 未传入的是否会被绑定
    sex = 'new sex'
    console.log(sex, arguments[2]) // undefined, new sex
    arguments[3] = 'new hobbit'
    console.log(hobbit, arguments[3])  //  undefined, new hobbit
}

foo('name', 'age')

传入的参数,实参和arguments的值会被共享,当没有传入的时候,实参与arguments不会共享。

以上都是非严格模式下,在严格模式下,实参和arguments是不会共享的

传递参数

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

function foo(){
    bar.apply(this, arguments)
}
function bar(a,b,c){
    console.log(a,b,c)
}
foo(1,2,3)  // 1,2,3

ES6展开运算符

function func(...arguments) {
    console.log(arguments)
}
func(1,2,3)  // 1,2,3

应用

arguments的应用其实很多,例如:

  1. 参数不定长
  2. 函数柯里化
  3. 递归调用
  4. 函数重载
  5. ......
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。