数据类型
基本数据类型
Number String Boolean undefined null BigInt Symbol
引用数据类型
Object[Array、Function]
Array
属于内置对象
数组相关操作
构造函数创建
var arr = new Array() //创建数组(真实数组)
arr[1] = 'a' //数组赋值
arr[2] = 1
arr[3] = true
console.log(arr[0]) //读取数组元素
console.log(arr.length) //读取数组长度
for(var i=0;i<arr.length;i++){ //遍历数组
console.log(arr[i])
}
//字面量创建
var arr = [1,2,3] //创建数组(真实数组)
console.log(arr[0]) //读取数组元素
console.log(arr.length) //读取数组长度
for(var i=0;i<arr.length;i++){ //遍历数组
console.log(arr[i])
}
一维数组与二维数组元素读取
判断变量是否为数组
typeof判断数组 null与对象时都显示结果为Object
方法一 Array.isArray(()):
let arr = [1,2,3]
console.log( Array.isArray(arr) ) //true
方法二 通过构造器判断:
let arr = [1,2,3]
console.log( arr.constructor ) //ƒ Array() { [native code] }
方法三 通过原型对象:
let arr = [1,2,3]
console.log( Array.prototype.isPrototypeOf(arr) ) //true
数组方法
静态方法
1、Array.isArray(arr)
判断是否为数组
2、Array.from(arr[, Fn])
将伪数组转换为新的真实数组并返回(可以说是浅拷贝出来一个同内容的真实数组出来),不改变原数组
Array.from('abc') //['a','b','c']
let arr=[1,2,3]
console.log( Array.from(arr,item=>item+1) ) //[2,3,4]
let arrayLike={
'0':'aaa',
'1':'bbb',
'2':'ccc',
'3':'ddd',
length:4
}
let arr=Array.from(arrayLike) //将伪数组转换为真正的数组
//下面代码将数组每个值+‘ED’
let arr2=Array.from(arrayLike, item=>item+'ED')
console.log(arr); //['aaa', 'bbb', 'ccc', 'ddd']
console.log(Array.isArray(arr)); //true
console.log(arr2); //['aaaED', 'bbbED', 'cccED', 'dddED']
console.log(Array.isArray(arr2)); //true
3、Array.of(arr)
将元素转换为真实数组
Array.of(1,2,3) [1,2,3]
原型方法
arr.toString()
数组=>字符串
1、数组元素添加
arr.push(元素) 将元素添加到数组arr的末尾,改变原数组
arr.unshift(元素) 将元素插入到数组arr的开头,改变原数组
2、数组元素删除
arr.pop() 删除数组arr的最后一个元素,改变原数组
arr.shift(元素) 删除数组arr的第一个元素,改变原数组
3、arr.slice(value1,value2) 截取数组,包括索引value1不包括索引value2
返回新数组,不改变原数组。
arr=['A','B','C','D','E']
let arr1=arr.slice(1,4)
console.log(arr) //['A','B','C','D','E']
console.log(arr1) //['B','C','D']
['A','B','C','D','E'].slice(3,-3) //[]
['A','B','C','D','E'].slice(0,-3) //['A','B']
['A','B','C','D','E'].slice(1,-3) //['B']
4、arr.splice(value1,value2[,value3]) 索引value1表示开始,value2表示删除的元素的个数,删除范围内的元素,其余删除,value3为用来替代的值
改变原数组,返回值为被删除的元素所形成的数组
arr=['A','B','C','D','E']
let arr1=arr.splice(1,3)
console.log(arr) //['A','E']
console.log(arr1) //['B','C','D']
============================两个arr不为同一个
arr=['A','B','C','D','E']
let arr1=arr.splice(1,3,1)
console.log(arr) //['A',1,'E']
console.log(arr1) //['B','C','D']
5、arr.fill(value1,value2[,value3]) value1表示填充值,value2填充起始索引,value3填充结束索引[不包含结束索引]
改变原数组
arr=['A','B','C','D','E']
let arr1=arr.fill(1,1)
console.log(arr) //['A', 1, 1, 1, 1]
console.log(arr1) //['A', 1, 1, 1, 1]
============================两个arr不为同一个
arr=['A','B','C','D','E']
let arr1=arr.fill(1,1,3)
console.log(arr) //['A', 1, 1, 'D', 'E']
console.log(arr1) //['A', 1, 1, 'D', 'E']
6、arr1.concat(arr2) 数组连接
返回新数组,不改变原数组。
let arr1=[1,2,3]
let arr2=[4,5,6]
console.log(arr1.concat(arr2))
7、arr1.join(arr2) 数组=>字符串,以特定字符分隔
不改变原数组
let arr1 = [1,2,3]
let arr2 = arr.join('*')
console.log(arr1) //[1, 2, 3]
console.log(arr2) //1*2*A*B*A*3
8、str.split(字符) 字符串方法 字符串=>数组,以特定字符转为数组
let str='a|b|c|d|adc'
console.log(str.split('|') ) //['a', 'b', 'c', 'd', 'adc']
9、arr.reverse() 数组反转
改变原数组
let arr1=[1,2,3]
let arr2 = arr1.reverse()
console.log(arr1) //[3, 2, 1]
console.log(arr2) //[3, 2, 1]
10、arr.sort() 数组排序 如果数组每一项为字符串,通过每个字符串首字符UTF-16 代码单元值序列排序(0-9 A-Z a-z 中文文本)
改变原数组
let arr1=[55,05,1,'二','B',01,'b','bi',2,'04','ai','!','a',88,'A','_','一',0,3]
let arr2 = arr1.sort()
console.log(arr1) //['!', 0, '04', 1, 1, 2, 3, 5, 55, 88, 'A', 'B', '_', 'a', 'ai', 'b', 'bi', '一', '二']
console.log(arr2) //['!', 0, '04', 1, 1, 2, 3, 5, 55, 88, 'A', 'B', '_', 'a', 'ai', 'b', 'bi', '一', '二']
let arr1 = [1,2,3]
let arr2 = arr1.sort((a,b)=>a-b)
console.log(arr2) //[1,2,3]
let arr1 = [1,2,3]
let arr2 = arr1.sort((a,b)=>d-a)
console.log(arr2) //[3,2,1]
11、arr.indexOf(value1[,value2]) 从左开始查找数组元素,返回第一次查找到该元素的索引位置,找不到返回-1 value1表示要查找的元素,value2为开始查找的起始索引 通常value2>=0
不改变原数组
let arr=[1,2,'A','B','A',3]
console.log(arr.indexOf('A')) //2
12、arr.lastIndexOf(value1[,value2]) 从右开始查找数组元素,返回第一次查找到该元素的索引位置,找不到返回-1 value1表示要查找的元素,value2为开始查找的起始索引 通常value2<=-1
不改变原数组
let arr=[1,2,'A','B','A',3]
console.log(arr.lastIndexOf('A')) //4
13、arr.includes(value1[,value2]) 判断数组是否存在某一元素,返回布尔值,value2为开始查找的起始索引 value2通常>=0,value2的正负不会影响查找的顺序
let arr=[1,2,'A',3]
console.log(arr.includes('A')) //true
高价函数
14、arr.find(Fn) arr中找到并返回满足Fn条件的第一个元素
不改变原数组
let arr=[1,2,'A',3]
console.log(arr) //[1, 2, 'A', 3]
console.log(arr.find(item=>item>0)) //1
15、arr.findIndex(Fn(item,index)) arr中查找数组中第一个符合条件的元素的索引,如果没找到返回-1
let arr=[1,2,'A',3]
console.log(arr) //[1, 2, 'A', 3]
console.log(arr.findIndex(item=>item>0)) //0
console.log(arr.findIndex(item=>item<0)) //-1
16、arr.filter(callbackFn(item,index,arr){}) 过滤数组,返回满足callbackFn条件的元素组成的数组
返回新数组,不改变原数组。
let arr=[1,2,5,3,8]
let arr1 = arr.filter((item)=>item>5)
console.log(arr) //[1, 2, 5, 3, 8]
console.log(arr1) //[8]
17、arr.map(callbackFn(item,index,arr){}) 计算原数组的每一项,返回计算后每个新元素组成的新数组
返回新数组,不改变原数组。
arr=[1,2,3]
let arr1 = arr.map(item=>item*2)
console.log(arr) //[1, 2, 3]
console.log(arr1) //[2, 4, 6]
arr=[1,2,3]
console.log(arr.map(parseInt)) //[1,NaN,NaN]
分析:
map展开:
arr.map(function(item,index,arr))
parseInt展开:
parseInt(string[,radix]) //string表示传递过来的字符串参数,radix表示该参数解析所用的进制,范围:2~36整数,如果数字不是2、8、10、16,返回NaN,如果数字为0,相当于没有写radix,没有第三个参数
arr.map(parseInt)=[parseInt,parseInt,parseInt]
=[parseInt(item,index,arr),parseInt(item,index,arr),parseInt(item,index,arr)]
=[parseInt(1,0,[1,2,3]),parseInt(2,1,[1,2,3]),parseInt(3,2,[1,2,3])]
=[1,NaN,NaN]
18、arr.reduce(callbackFn(prevItem,nowItem,nowindex){},初始值)
每次取数组两个值,将两值进行运算,将当前循环的计算结果保存在prevItem中,当前循环计算结束后再将prevItem与后面一个数组元素进行相同运算,以此类推,把最终结果返回,不改变原数组
prevItem表示前一个数组元素,nowItem表示当前数组元素,index表示当前所在的索引
版本一,不设置初始值
arr.reduce(callbackFn(prevItem,nowItem,nowindex){})
不设置初始值时,第一次循环时,prevItem取arr[0],nowItem取arr[1],nowindex从1开始
arr=[1,2,3,4]
let arr1 = arr.reduce((prevItem,nowItem,nowindex)=>{
console.log(prevItem,nowItem,nowindex)
return prevItem+nowItem
})
console.log(arr1) //10
版本二 设置初始值
arr.reduce(callbackFn(prevItem,nowItem,nowindex){},初始值)
设置初始值时,第一次循环时,prevItem取设置的初始值,nowItem取arr[0],nowindex从0开始
arr=[1,2,3,4]
let arr1 = arr.reduce((prevItem,nowItem,nowindex)=>{
console.log(prevItem,nowItem,nowindex)
return prevItem+nowItem
},5)
console.log(arr1) //15
var products=[
{ pid:101,pname:'华为nova10 128g',price:2998, num:5 },
{ pid:102,pname:'华为nova10 256g',price:2997, num:3 },
{ pid:103,pname:'华为nova10 pro 128g',price:3600, num:4 }
]
var total = products.reduce((prevItem,nowItem)=>{
return prevItem + nowItem.num
},0)
console.log(total) //12
19、arr.some(Fn) 一真即真
返回布尔值
arr=[1,2,3]
let result = arr.some(function(item){
return item>2
})
console.log(result) //true
20、arr.every(Fn) 一假即假
返回布尔值
arr=[1,2,3]
let result = arr.every(function(item){
return item>2
})
console.log(result) //false
22、arr.at(index) 相当于arr[index]
let arr = ['a','b','c']
arr.at(-1) //'c'
arr.[-1] //相当于arr.['-1'] undefined
let arr = ['a','b','-1','c']
arr.[-1] //相当于arr.['-1'] undefined
22、arr.flat(Int) 数组扁平化,不改变原数组创建新数组
Int <0 新数组与旧数组完全一致,没有任何变化
Int <数组内嵌套层级 多维数组完全转变为一维数组并且去除数组内元素value为空的元素
Int 为 Infinity 无论数组嵌套多少层都会实现扁平化,并且去除数组内元素value为空的元素
[1, , 3, ["a", ,null,undefined,"c"]].flat(1) //[1, 3, 'a', null, undefined, 'c']
[1, , [3, ["a", ,null,undefined,"c"]]].flat(Infinity) //[1, 3, 'a', null, undefined, 'c']
[1, , 3, ["a", ,null,undefined,"c"]].flat(-1) //[1, , 3, ["a", ,null,undefined,"c"]].flat(1)
可以根据伪数组的length将数组进行扁平化,(可以遍历到用Object.defineProperty增加的属性)嵌套的伪数组扁平化不了
const arrayLike = {
length: 6,
0: [1, 2],
// 嵌套的类数组对象不会被展平
1: { length: 2, 0: 3, 1: 4 },
2: 5,
4:6
};
Object.defineProperty(arrayLike,'5',{
enumerable:false,
get(){
return '我是5'
},
set(){
}
})
console.log(arrayLike) //{0: [1, 2], 1:{0: 3, 1: 4, length: 2}, 2: 5, 4: 6, length: 6}
console.log(Array.prototype.flat.call(arrayLike)); [1, 2, {0: 3, 1: 4, length: 2}, 5, 6, '我是5']
迭代
for …in 能迭代数组、对象
使用场景:改变数组对象里所有元素(对象)的某一属性属性值
let obj={
info1:'111',
info222:'222',
info333:'333',
}
for(const key in obj){ //输出可枚举属性
console.log(key) //info1 info222 info333
console.log(obj[key]) //'111' '222' '333'
}
let arr =[1,2,3]
for(const key in arr){
console.log(key) //'0' '1' '2'
console.log(arr[key]) //1 2 3
}
for …of 只能迭代数组
使用场景:改变数组对象里所有元素(对象)的某一属性属性值
let obj={
info1:'111',
info222:'222',
info333:'333',
}
for(const iterator of obj){ //报错 caught TypeError: obj is not iterable
console.log(iterator )
console.log(obj[iterator ])
}
let arr =[1,2,3]
for(const iterator of arr){
console.log( iterator ) //1 2 3
}
用for…of迭代对象
let obj={
info1:'111',
info222:'222',
info333:'333',
}
for(const iterator of Object.keys(obj)){
console.log(iterator) //info1 info222 info333
console.log(obj[iterator]) //111 222 333
}
for
let arr =[1,2,3]
for(var i=0;i<arr.length;i++){
console.log(arr[i]) //1 2 3
}
forEach //不提倡使用forEach循环改变数组每一项,可以使用map代替
forEach与map区别:map返回新数组,不改变原数组的每个值;forEach改变原数组中每个元素的值,return返回值为undefined
let arr =[1,2,3]
arr.forEach(item=>{
console.log(item) //1 2 3
})
如何判断数据是否能迭代
判断typeof 数据[Symbor.iterator] 是否为函数,是就可迭代,否则不可迭代,它返回布尔值
let obj={
info1:'111',
info222:'222',
info333:'333'
}
console.log( typeof obj[Symbol.iterator] == 'function' ) //false
Array.of() 、[ ]和 Array() 构造函数的区别
Array.of(3) //[3]
[3] //[3]
Array(3) //[ , , ]
Array.of(1,2,3) //[1,2,3]
[1,2,3] //[1,2,3]
Array(1,2,3) //[1,2,3]
伪数组
不具有数组方法的数组,具有length,可以通过下标访问数据,能够用for遍历但不能用forEach、each遍历
数组的判定方法
不能使用typeof,typeof会查找原型链
Array.isArray(arr)
var arr = [1,2,3]
console.log(Array.isArray(arr)) //true
arr instanceof Array 判断对象是否是某个构造函数的实例
var arr = [1,2,3]
console.log(arr instanceof Array) //true