JS 基础之数组

96
饥人谷_养乐多
0.1 2019.04.13 07:27* 字数 2244

一、数组

1. 定义
  • 数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示。
var arr = ['a', 'b', 'c'];
  • 任何类型的数据,都可以放入数组。
  • 如果数组的元素还是数组,就形成了多维数组。
2. 数组的本质

本质:数组属于一种特殊的对象。typeof 运算符返回数组的类型是 object.
特殊性:数组的键名是按次序排列的一组整数(0,1,2…)

  • 数组的键名其实也是字符串。可以用数值读取,是因为非字符串的键名会被转为字符串。这点在赋值时也成立,先转成字符串再进行赋值。
var arr = ['a', 'b', 'c'];
arr['0'] // 'a'
arr[0] // 'a'
  • 因为数值键名不符合标识符规范,不能使用点结构读取,数组成员只能用方括号 arr[0]arr['0'] 读取
3. length 属性
  • 数组的 length 属性,返回数组的成员数量。
  • 只要是数组,就一定有 length 属性。length 是动态的值,等于键名中的最大整数加上 1.
var arr = ['a', 'b', 'c'];
length.arry   // 3

arr[9] = 'e';
arr.length // 10
  • JavaScript 使用 32 位整数保存数组的元素个数。这意味着,数组成员最多只有 4294967295 个(2^32 - 1)个,因此 length 属性的最大值是 4294967295。
  • length 属性是可写的。若设置一个小于当前成员个数的值,该数组的成员会自动减少到 length 设置的值。
  • 清空数组的一个有效方法,就是将 length 属性设为0。
  • 若设置 length 大于当前元素个数,则数组的成员数量会增加到这个值,新增的位置都是空位。
var arr = [ 'a', 'b', 'c' ];
arr.length // 3

arr.length = 4
arr[3]   //undefined
arr.length = 2;
arr // ["a", "b"]
arr.length = 0;
arr // []
  • 由于数组本质上是一种对象,所以可以为数组添加属性,但是这不影响 length 属性的值。
var a = [];

a['p'] = 'abc';
a.length // 0
a[2.1] = 'abc';
a.length // 0
4. in 运算符
  • 检查某个键名是否存在,适用于对象,也适用于数组。
  • 注意,如果数组的某个位置是空位,in运算符返回false。
var arr = [];
arr[100] = 'a';

100 in arr // true
1 in arr // false
5. 遍历数组
  • for...in 循环可以遍历数组,但它不仅遍历数字键,还遍历非数字键。所以可以使用 for 循环或 while 循环遍历数组。
  • 数组的 forEach 方法也可以用来遍历数组:
var colors = ['red', 'green', 'blue'];
colors.forEach(function (color) {
  console.log(color);
});
// red
// green
// blue
6. 数组的空位
  • 当数组的某个位置是空元素,即两个逗号之间没有任何值,我们称该数组存在空位(hole)。
  • 数组的空位是可以读取的,返回 undefined。
  • 用 delete 命令删除一个数组成员,会形成空位,且不影响 length 属性。
var a = [1, , 1];
a.length // 3
a[1]   // undefined

delete a[2];
a.length // 3
  • 空位:表示数组没有这个元素,遍历数组时空位会跳过
    undefined:表示数组有这个元素,值是 undefined,遍历不会跳过
7. 类似数组的对象

对象的所有键名都是正整数或零,并且有 length 属性,语法上称为“类似数组的对象”(array-like object):

var obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};
  • 这种length属性不是动态值,不会随着成员的变化而变化。
  • 类似数组的对象(array-like object)并不是数组,instanceof 运算符返回 false
arrayLike instanceof Array   // false

二、Array 对象

1. 构造函数

Array 是 JavaScript 的全局对象,同时是构造数组的一个构造函数。

  1. 基本用法,以下三种写法都可以:
let f = new Array('a,' 'b')
let f = Array('a,' 'b')
let f = ['a', 'b']  // 常用方法
f // ["a", "b"]

对于基本类型 Number、String 和 Boolean,构造函数时不加 new 创建的的是对应的基本类型,加 new 创建的是对象;对于复杂类型 Object(包括 Array 和 Function),加与不加 new 创建的都是对象。

  1. 创建空数组:
var a = new Array(3)
a  // [empty * 3]
a.length   // 3

Array 构造函数的参数 3,表示生成一个长度为 3 的数组,每个位置都是空值:
创建数组
  1. 不一致性
var a = new Array(3, 3)
// [3, 3]

上面的例子,第一个参数不再指数组的长度,说明 Array 作为构造函数具有不一致性。内存图解:
不一致性
2. JS 中数组的本质
  1. 我们对数组的理解:数组就是数据的有序集合。
    JS 对数组的理解:数组就是原型链中有 Array.prototype 的对象。
  • Array 既有valueOf()toString()等所有对象都拥有的静态方法,还有push()pop()shift()join()等 Array 独有的方法(Array.prototype)。
  1. Array 与 Object 的区别
var a = [1,2,3]
var obj = {0:1, 1:2, 2:3, length:3}

二者的内存是没有区别的,它们的区别是原型不同。内存图解:
Array 与 Object 的区别
3. 伪数组
  • 定义:一个对象,有 0,1,2,3,4,5...n,length 这些 key,但原型链中没有 Array.prototype,这样的对象就是伪数组。
  • 目前知道的伪数组有
    arguments 对象
    document.querySelectAll('div') 返回的对象
    伪数组 arguments
4. 数组的 API

API:浏览器提供的接口。

  1. Array.prototype.forEach:遍历
  • forEach() 方法对数组的所有成员依次执行参数函数。forEach() 方法的参数是一个函数,该函数接受三个参数:当前值value、当前位置key、整个数组。
  • 它不返回值,只用来操作数据。
arr.forEach( function(){} ) 
forEach()
  • for i 循环和 Array.prototype.forEach 都可以遍历数组,二者区别为:
    for 是关键字,不是函数;Array.prototype.forEach 是一个函数。
    for 循环可以 breakcontinueArray.prototype.forEach 不支持 breakcontinue.
  1. Array.prototype.sort:排序
    sort() 方法的内置排序一般是快排。排序后,原数组被改变
    默认按照字典顺序排序,若想自定义排序,可传入一个函数作为参数。
    sort()
  • 返回 (x-y)和返回(y-x)的排序结果是不同的,一个从小到大排序,一个从大到小排序。
  1. Array.prototype.join:连接数组成员为字符串
    join() 方法以指定参数作为分隔符,将所有数组成员连接成一个字符串。
    如果不提供参数,默认用逗号分隔。

    join()

  2. Array.prototype.concat:合并多个数组
    concat() 方法用于多个数组的合并。将新数组的成员添加到原数组成员的后部,然后返回一个新数组,原数组不变。

    concat()

  • 特殊用法:用来复制一个数组。把当前数组 concat 一个空数组[],返回一个新的数组。
  1. Array.prototype.map:映射
  • map() 方法将数组的所有成员依次传入参数函数(与 forEach 相同),然后把每一次的执行结果组成一个新数组返回(与 forEach 不同)。
  • map()方法也接受一个函数作为参数,该函数调用时,map() 方法向它传入三个参数:当前值value、当前位置key和数组本身。
    map()
  1. Array.prototype.filter:过滤
  • filter() 方法用于过滤数组成员,满足条件的成员组成一个新数组返回。
  • 它的参数是一个函数,所有数组成员依次执行该函数,返回结果为 true 的成员组成一个新数组返回。该方法不会改变原数组。
    filter()
  • 链式操作,同时使用 filtermap 方法:
    链式操作
  1. Array.prototype.reduce
    reduce() 方法从左到右依次处理数组的每个成员(从第一个成员到最后一个成员),最终累计为一个值。
    reduce()
    上面代码中,reduce 方法求出数组所有成员的和。第一个参数是一个函数,sum 为之前求和的结果,n 为当前数字,最后一个参数 0 是初始值。
  • mapfilterreduce 表示:
    map 和 filter 用 reduce 表示
  1. Array.prototype.reverse:颠倒
    reverse() 方法用于颠倒排列数组元素,返回改变后的数组。该方法会改变原数组

    reverse()

  2. Array.prototype.slice:提取

  • slice() 方法用于提取目标数组的一部分,返回一个新数组,原数组不变。
arr.slice(start, end)
  • 它的第一个参数为起始位置(从 0 开始),第二个参数为终止位置(不包含该位置的元素本身)。如果省略第二个参数,则一直返回到原数组的最后一个成员。
    slice()
  • 特殊用法:最后一个例子 slice 没有参数,实际上等于返回一个原数组的拷贝。
  1. Array.prototype.splice:删除
  • splice() 方法用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。该方法会改变原数组
arr.splice(start, count, addElement1, addElement2, ...)
  • splice 的第一个参数是删除的起始位置(从0开始),第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。
    splice()
  • 如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组:
    splice() 一个参数
  1. 例题:var a = [1,2,3,4,5,6,7,8,9],计算所有奇数的和。
var a = [1,2,3,4,5,6,7,8,9]
a.reduce(function(arr, n){
    if(n % 2 !== 0){
        arr.push(n)
    }
    return arr
},[]).reduce(function(sum, n){
    return sum + n
},0)

// 或者
a.reduce( (sum,n)=> {
    return n%2===1 ? sum + n : sum
}, 0)
前端探索
Web note ad 1