【JS标准库-2】数组对象

284 阅读4分钟

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,那么就可以将其转化为数组 image

如图所示,我设置了一个伪数组,有下标,有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[, ...]]]]) image

遍历

数组也可以使用对象的方法Object.keys,Object.values,for in来遍历数组。但是这些方法都不是很好,会遍历出不想要的东西。例如image

所以推荐使用for或者forEach来遍历数组。区别是forEach不支持中断(breakreturncontinue),并且forEach产生的是函数作用于,for循环产生的是块级作用域。

语法: arr.forEach(callback(currentValue [, index [, array]])[, thisArg])

image

我们可以简单利用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]就是累计器的初始值。 image.png

可以见这篇详解www.jianshu.com/p/e375ba1cf…