JS中的数组
JS中没有真正的数组,js的数组实际上是由对象模拟产生的。
每个数组都由keys(下标)、值、length、数组的共有属性Array.prototype组成。例如下列一个数组:
总结一下js中的数组构成:下标(下标typeof为字符串)、值、length、指向Array.prototype的__proto__。
伪数组
伪数组是另一种形式,除了长得像数组,也拥有下标、值、length,唯一的区别是伪数组没有数组的共有属性,或者说原型链上没有数组的原型。所以伪数组无法使用数组的共有方法。
比较典型的伪数组有arguments和大部分dom对象,还有字符串。
instanceOf 可以区分出数组和Object,也可以用来判断某对象是不是真数组
let a =(function(x,y,z){return arguments})(1,2,3)
a instanceof Array //false
我们可以通过Array.from()让伪数组变成真正的数组
let a =(function(x,y,z){return arguments})(1,2,3)
Array.from(a) instanceof Array //true
除了让伪数组变成真正的数组,我们还可以使用call让伪数组同样使用数组的方法。
let a =(function(x,y,z){return arguments})(1,2,3)
Array.prototype.forEach.call(a,function(v){
console.log(v)
})
//1 2 3
因为字符串类似数组,所以也可以使用这种方法,但是这种方法效率较慢,所以建议还是转成真正的数组
字符串转数组
String.prototype.split() 字符串的共有方法可以以指定的分隔符字符规则分割字符串,返回一个新数组。MDN(String.prototype.split)
数组的静态方法
Array.isArray()
使用typeof运算符是不可以判断一个数据类型是否为数组的,一般我们都使用Object.prototype.toString或者instanceof检测是否有数组的原型来分别是否为数组,现在新增Array.isArray()来帮助分辨是否为数组
let arr=[]
typeof arr //Object
arr instanceof Array //true
Array.isArray(arr) //true
数组的实例方法
Array.from 伪数组转数组
Array.from通过数组的内置方法可以将一个可迭代对象或者伪书组变成数组,可迭代对象例如字符串。
需要满足两个条件,有下标,有length,那么就可以将其转化为数组
如图所示,我设置了一个伪数组,有下标,有length,但是将其转化成数组,具体以length为准。Array.from
Array.prototype.slice 浅拷贝
Array.prototype.slice()返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括begin,不包括end)。原始数组不会被改变。
slice(0)方法可以浅拷贝一个数组。
Array.prototype.concat()方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
删
因为数组也是对象,所以可以使用对象方法来删除它的属性名+值
delete arr[0]但是这种方法不会改变字符串的长度,删掉的地方会保留empty,所以不推荐
修改数组的长度也可以删除数组的属性,也不推荐使用。
arr.shift从开头位置弹出(删除)数组的元素
arr.pop从末尾删除数组的元素
arr.splice这是一个强大的API,可以用来增加、修改、删除数组的元素。别说了,买它!!
语法:array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
查
遍历
数组也可以使用对象的方法Object.keys,Object.values,for in来遍历数组。但是这些方法都不是很好,会遍历出不想要的东西。例如
所以推荐使用for或者forEach来遍历数组。区别是forEach不支持中断(break、return、continue),并且forEach产生的是函数作用于,for循环产生的是块级作用域。
语法:
arr.forEach(callback(currentValue [, index [, array]])[, thisArg])
我们可以简单利用for来实现forEach
// 简单用for实现forEach
Array.prototype.newforEach = function (arrself,fn) {
for (let i = 0; i < arrslef.length; i++) {
fn(arr[i], i)
}
}
let arr = [1, 2, 3]
arr.newforEach(arr,function (v, item) {//把arr当参数
console.log(v, item);
})
实际上的forEach会让this替代传入的arrself参数,要不然数组调用方法时候把自己当成参数传进去也太丑了。。。下一篇再讲this。
查找
查看数组的方法很多,比如采用中括号arr[arr.length-1],有点类似于对象的查看方式,区别就是引号的问题。需要说明一点arr[1],这里面的1是字符串。
如果使用中括号的方式来查看元素,需要注意的是索引越界问题,js不像其他语言支持arr[-1],同理arr[length]也是不支持查看。所以说js中的数组实际上是对象模拟的。
find可以返回满足某个条件的元素
findinex可以返回满足某个条件的元素的下标
indexOf 可以查找元素在不在数组中,如果不在就返回0
增
数组可以通过arr[]=xxx的方式来增加元素,但是一般情况不是很建议,因为很容易出错。
以下方法会改变数组本身
arr.push()在数组的末尾添加元素
arr.unshift在数组的开头添加元素
arr.splice()牛逼的api,前面也提到了,买它!!
arr.reverse()说到reverse,有一道经典面试题,
问题:如何反转字符串?
我们可以先用Array.from(str)将字符串变成数组,再通过reverse反转数组,再把数组修改成字符串
let str = `string`
str = Array.from(str)
str.reverse()
str = str.join('')
console.log(str);
arr.sort() 可以对数组进行排序,传入的参数为一个比较函数。Array.prototype.sort()
主要可以看一下sort通过比较函数把对象和纯数字数组进行排序。
数组变换
以下方法不会改变原数组
arr.map() n变n,对数组中的所有元素进行遍历操作。
let arr = [1, 2, 3, 4, 5]
let arr1 = arr.map(function (v) {
return v * 2
})
console.log(arr1);
arr.filter n变少,filter就是过滤的意思,过滤满足条件的元素
let arr = [1, 2, 3, 4, 5, 6, 7, 8]
let arr1 = arr.filter(function (v) {
return v > 3
})
console.log(arr1);
实际上上面两个方法都是reduce语法糖
reduce n变1。超强api。MDN reduce
大概的思路就是两个参数,一个是回调函数,一个是initial。 回调函数的第一个参数是累计器accumulator
如果传入initial,那么就从索引0开始,对每个元素进行操作后,返回这个结果给累积器,实际上这个累计器就是initial。
如果不传入initial,那么从数组的第一个数开始索引,arr[0]就是累计器的初始值。
可以见这篇详解www.jianshu.com/p/e375ba1cf…