JS之数组

数组也是js中常用的数据类型,下面通过一些场景来描述它的使用。

判断变量类型,数组or对象

instanceof

instanceof用于判断构造函数的prototype属性是否出现在对象的原型链中的任何位置。

array也是引用类型,通过instanceof来判断变量是数组还是对象。但因为数组是属于对象的,所有判断全应该先是否为数组,再判断是否为对象。

可以封装一个函数

1
2
3
4
5
6
7
8
9
function myDataType(o){
if(o instanceof Array){
return 'Array'
}else if(o instanceof Object){
return 'Object'
} else{
return 'not is a object type'
}
}
construtor

也可以通过构造函数判断,因为每一个对象的实例都是通过构造函数生成的,所以可以直接判断constructor属性。

1
2
let a=[1,2,3]
console.log(a.constructor===Array)

construtor与__proto__ 属性:proto表示的是隐式原型,指向构造函数的原型

1
[].__proto__===[].constructor.prototype//true

可以对其进行封装

1
2
3
4
5
6
7
8
9
10
11
function myDataType(o){
let constructor=o.__proto__.constructor||o.constructor
if(constructor===Array){
return 'Array'
}else if(constructor===Object){
return 'Object'
} else{
return 'not is a object type'
}
}
}

但是早期ie不支持__proto__属性,因此并不完美。

toString()

任何数据类型都会包含toString()函数,通过借助call函数,通过toString的返回值进行判断。

1
2
let a=[1,2,3]
console.log(Object.prototype.toString.call(a))//[object Array]
Array.isArray()

使用这个方法可以直接判断是否为数组,但是不能判断是否为对象

1
2
let a=[1,2,3]
Array.isArray(a)//true

filter()函数过滤满足条件的值

filter返回一个满足条件的新数组,不改变原来的数组,可以通过自定义方法来过滤复杂数据类型的数组。filter接收一个函数作为参数,返回值为true的元素将被加入新数组。

还可以利用filter进行去重

reduce()

reduce作为累加器,理解它需要知道参数的意义,MDN中的定义如下

1
2
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
//[]内的参数为可选

其中accumulator:上一次调用回调时返回的累积值,或initialValue

currentValue:数组中正在处理的元素

index :数组中正在处理的当前元素的索引

array:数组本身

统计元素出现次数
1
2
3
4
5
6
7
	let countOccurrences=function(arr){
return arr.reduce(function(accumulator,currentValue){
accumulator[currentValue]?accumulator[currentValue]++:accumulator[currentValue]=1
return accumulator
},{})
}
console.log(countOccurrences([1,2,3,4,5,6,7]))

我自己在chrome上运行时,想偷个懒将函数名称写成count,然后报错

1
Identifier 'count' has already been declared

这样的函数名称不能在js中定义,可能因为是关键词或者保留字吧,换一个名称就行了。

多维度统计数据

场景:汇率不同,将一组人民币分别换算成美元和欧元

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let items = [{ price: 10 }, { price: 20 }, { price: 300 }]
let reduces = {
//分别计算不同汇率
totalEuros: function (state, item) {
return state.euros += item.price * 0.1265
},
totalDolls: function (state, item) {
return state.dolls += item.price * 0.1487
}
}
let managerReduces = function (reduces) {
return function (state, item) {
return Object.keys(reduces).reduce(
function (next, key) {
//此处next累加器只是占个位,因为真正的值都是reduces里面的函数返回的
reduces[key](state, item)
return state
}, {}
)
}
}
//将callback函数封装成manager,设置初始值
let totals = items.reduce(managerReduces(reduces), { euros: 0, dolls: 0 })
console.log(totals)
找出数组中的最值
  • Math.min

利用Math.min()和Math.max(),由于 minMath 的静态方法,所以应该像这样使用:Math.min(),而不是作为你创建的 Math 实例的方法(Math 不是构造函数)。

1
2
3
4
5
let nums=[1,3,0]
Array.prototype.min = function () {
return Math.min.apply({},this)
}
console.log(nums.min())//0

为Array类型添加静态函数min,apply传入的{},表示当前执行环境的全局对象,this代表传入的数组。不能直接调用,除非直接传入数据👇,但是实际开发中传入的往往是数组

1
let minNum=Math.min(1,3,0)
  • reduce
1
2
3
4
5
6
Array.prototype.min = function () {
return this.reduce(function(pre,cur){
// 比较,返回较小的数
return pre>cur?cur:pre
})
}
  • sort

原生的sort排序后直接取值

1
2
3
4
//最小值
nums.sort((a, b) => a - b)[0])
//最大值
nums.sort((a, b) => a - b)[nums.length-1])

还有for循环就不说了

数组遍历

有for、forEach()、map()、filter()、reduce()、find()、some()+every()函数的方法

其中,find是es6新添加的,其他都是es5新增的,所以我们可以做兼容性处理(手动实现API

查看评论