Please enable Javascript to view the contents

从头学习js-13-类数组对象与arguments

 ·  ☕ 2 分钟

这个系列是我读冴羽老师博客的感悟,
加入了个人的解读和练习题的解答

类数组

在之前模拟实现apply和bind时我们其实已经遇见过arguments这样的类数组文件了

1
2
3
4
5
6
7
var array = ['A', 'B', 'C']
var arrayLike = {
  0: 'A',
  1: 'B',
  2: 'C',
  lenght: 3
}

类数组文件的读取,遍历方式和数组一样

1
2
3
4
5
6
7
8
array[0]
arrayLike[0]

array.length
arrayLike.length

for(var i=0; i<array.length; i++){}
for(var i=0; i<arrayLike.length; i++){}

但是类数组终究不是数组不能调用数组的原型方法,比如push、splice、slice

常用的做法是Array.prototype.splice.call(arrayLike, 2)
利用call在直接调用Array原型方法的时候把this指向arrayLike对象

另外经常需要把类数组对象转为数组,方法如下:

1
2
3
4
5
Array.prototype.slice.call(arrayLike) //slice 用于截取数组从start到end,省略end时默认到数组末尾
Array.prototype.splice.call(arrayLike, 0) //splice 可以插入删除,参数index, deleteNumber, item1,...,itemX
Array.prototype.concat.call([], arrayLike)
Array.from(arrayLike) //es6 Array.from
[...arguments] //es6 拓展运算符

Aruguments对象

在函数体中arguments指代函数的Arguments对象

Aruguments的length,指的是实参的长度

Arguments的callee通过它可以调用函数本身

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//用callee来解决之前第8篇中的for循环无法保存i到函数内部的问题

var data = []

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

data[0](); //0
data[1](); //1
data[2](); //2

乍一看在for循环中的那部分有点奇怪,我们拆开看
xxx.i = i 是在xxx的属性i赋值为i

括号内:
data[i] = 某个东西

(data[i] = 赋值内容).i = i 其实就是
data[i].i = i

接下来看赋值的内容
是一个函数对象,函数对象在创建的时候不会执行内部的代码
argument.callee 指的就是 data[i]
argument.callee.i 自然就是data[i].i

那因为纯的赋值 = xx 会在for循环里立即执行,所有i的每个状态都会存在对应的data[x]里


arguments 和对应参数的绑定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function foo(name, age, sex, hobbit) {

    console.log(name, arguments[0]); // name name

    // 改变形参
    name = 'new name';

    console.log(name, arguments[0]); // new name new name

    // 改变arguments
    arguments[1] = 'new age';

    console.log(age, arguments[1]); // new age new age

    // 测试未传入的是否会绑定
    console.log(sex); // undefined

    sex = 'new sex';

    console.log(sex, arguments[2]); // new sex undefined

    arguments[3] = 'new hobbit';

    console.log(hobbit, arguments[3]); // undefined new hobbit

}

foo('name', 'age')

传入参数时,实参和arguments的值会共享,没有传入参数时,实参和arguments的值不会共享
在严格模式下都不会共享


传递参数

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

1
2
3
4
5
6
7
8
9
//利用apply的第二个参数可以直接传一个数组
function foo(){
  bar.apply(this, [...arguments])
}
function bar(){
  console.log(a, b, c)
}

foo(1, 2, 3)
分享

Llane00
作者
Llane00
Web Developer