2

数组定义

  • 数组是按次序排列的一组值
  • 每个值都有编号,从0开始
  • 可以在定义时赋值,也可以先定义后赋值
  • 任何类型的数据都可以存入数组

           
       const arr = [
           {a: 1},
           [1, 2, 3],
           function(){}
       ];

数组的本质

  1. 本质上,数组属于一种特殊的对象,它的键名是按次序排列的一组整数(0,1,2...)

    typeof [1, 2, 3] //"object"

  2. 数组成员的键名是固定的,因此不用为每个元素指定键名,而对象的每个成员都必须指定键名

    const arr = ['a', 'b', 'c'];
    Object.keys(arr) //['0', '1', '2']

JavaScript语言规定,对象的键名一律为字符串

const arr=['a', 'b', 'c'];
arr['0'] //'a'
arr[0] //'a'

之所以可以用数值读取,是因为非字符串的键名会被转为字符串

注意:这一点在赋值时也成立!

let a = [];
a[1.00] = 6;
a[1] // 6

“1.00”转成字符串是“1”

读取数组成员的方法

  • object.key
  • object[key]

length属性

  • 该属性是一个动态的值,等于键名中的最大整数加1
  • 该属性是可写的,如果人为设置一个小于当前成员个数的值,该数组的成员就会自动减少到length设置的值

       let arr = ['a', 'b', 'c'];
       arr.length // 3
       arr.length = 2;
       arr // ['a', 'b']
    
  • 如果人为设置一个大于当前成员个数时,新增的位置都是空位,读取新增的位置都会返回undefined

       let arr = ['a'];
       arr.length = 3;
       arr[1] // undefined
    
  • 数组本质是一种对象,所以可以为数组添加属性,但并不影响length属性的值

       let arr = [];
       arr['p'] = 'abc';
       arr.length // 0
       arr[2.1] = 'abc';
       arr.length // 0
       arr['1'] = 'a';
       arr.length // 2

in运算符

  • 检查某个键名是否存在,适用于对象,也适用于数组
  • 键名都是字符串,数值会自动转成字符串

       const arr = ['a', 'b', 'c'];
       2 in arr // true
       '2' in arr // true
       4 in arr // false
    
  • 如果数组的某个位置是空位,in运算符返回false

       let arr = [];
       arr[100] = 'a';
       100 in arr // true
       1 in arr // false

for...in循环和数组的遍历

  • 可以遍历对象,也可以遍历数组(数组是一种特殊对象)

       const arr = [1, 2, 3];
       for(let i in arr) {
           console.log(arr[i]);
       }
       // 1
       // 2
       // 3
    
  • 不仅会遍历数组所有的数字键,还会遍历非数字键

       let arr = [1, 2, 3];
       arr.foo = true;
       for(let key in arr) {
           console.log(key);
       }
       // 0
       // 1
       // 2
       // foo

数组的空位

当数组的某个位置是空元素(两个逗号之间没有任何值),我们称该数组存在空位
const a = [1, , 1];
a.length // 3
  • 数组的空位不影响length属性
  • 如果最后一个元素后面有逗号,并不会产生空位
  • 数组的空位是可以读取的,返回undefined
  • 使用delete删除一个数组成员,会形成空位,但并不会影响length属性

       let arr = [1, 2, 3];
       delete arr[1];
       arr[1] // undefined
       ar.length // 3

length属性不过滤空位

如果是空位,使用数组的forEach方法、for...in结构、Object.keys方法进行遍历,空位都会被跳过

const a = [, , ,];
a.forEach(function (con, key) {
    console.log(key + '.' + con);
})
// 不输出任何内容

for(let key in a) {
    console.log(key);
}
// 不输出任何内容

Object.keys(a)
// []

如果是undefined,遍历时不会被跳过

const a = [undefined, undefined, undefined];
a.forEach(function (con, key) {
    console.log(key + '.' + con);
});
// 0.undefined
// 1.undefined
// 2.undefined

for(let key in a) {
    console.log(key);
}
// 0
// 1
// 2

Object.keys(a)
// ['0', '1', '2']

也就是说,空位是数组没有这个元素,不会被遍历到,但是undefined表示数组有这个元素,它的值是undefined,所以会被遍历到

map()

将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回
let numbers = [1, 2, 3];
numbers.map(n => n+1); // [2, 3, 4]
console.log(numbers); // [1, 2, 3]
map方法接受一个函数作为参数,该函数调用时,map方法向它传入三个参数:当前成员、当前位置、数组本身
[1, 2, 3].map((elem, index, arr) => elem * index );
// [0, 2, 6]
map还可以接受第二个参数,用来绑定回调函数内部的this变量
const arr = ['a', 'b', 'c'];
[1, 2].map(function(e) {
    return this[e];
}, arr);
// ['b', 'c']
如果数组有空位,map方法的回调函数在这个位置不会执行,会跳过数组的空位,但是不会跳过undefined和null
let f = (n) => 'a';
[1, undefined, 2].map(f) // ['a', 'a', 'a']
[1, null, 2].map(f) // ['a', 'a', 'a']
[1, , 2].map(f) // ['a', , 'a']

forEach()

对数组的所有成员依次执行参数函数,但是不返回值,只用来操作数据

forEach的用法与map方法一致,参数是一个函数,该函数同样接受三个参数:当前值、当前位置、整个数组

forEach方法也可以接受第二个参数,绑定参数函数的this变量

forEach方法也会跳过数组的空位,但是不会跳过undefined和null

如果数组的遍历是为了得到返回值,就使用map(),不然就使用forEach()方法

类似数组的对象

如果一个对象的所有键名都是正整数或零,并且有length属性,那么这个对象就很像数组,称为“类似数组的对象”
const obj = {
    0: 'a',
    1: 'b',
    2: 'c',
    length: 3,
}
obj[0] // 'a'
obj[1] // 'b'
obj.length // 3
obj.push('d') // TypeError: obj.push is not a function
  • 类似数组的对象的根本特征是具有length属性,但是这个length属性不是动态值,不会随着成员的变化而变化

    let obj = {

    length: 0,

    };
    obj[3] = 'd';
    obj.length // 0
    obj.foo = 'hhh';
    obj // {3: "d", length: 0, foo: "hhh"}

  • 类似数组的对象不具备数组特有的方法

典型的“类似数组的对象”

1、arguments对象

function args() { return arguments }
const arrayLike = args('a', 'b');

arrayLike[0] // 'a'
arrayLike.length // 2
arrayLike instanceof Array // false

2、大多数DOM元素集

const elts = document.getElementsByTagName('p');
elts.length // 3
elts instanceof Array // false

3、字符串

'abc'[1] // 'b'
'abc'.length // 3
'abc' instanceof Array // false

类数组变成真正的数组

slice方法

let arr = Array.proptotype.slice.call(arryLike);

类数组使用数组的方法

通过call()把数组的方法放到对象上

function print(value, index) {
    console.log(index + ':' + value);
}
Array.prototype.forEach.call(arrayLike, print);

// 等同于for循环
function example() {
    for(let i=0; i< arguments.length; i++) {
        console.log(i + '.' + arguments[i])'
    }
}    

通过call(),把forEach()方法放到arrayLike上面调用


pitaojin
326 声望36 粉丝