JS对象类型-数组方法篇

继承方法

继承自对象的方法有三种:toString()、toLocaleString()和valueOf()

toString()

toString()方法返回数组中元素以逗号分隔的字符串。同不传参的join()方法表现效果一样。

[1,2,3].toString() // '1,2,3'
[1,2,3].join() // '1,2,3'

toLocaleString()

toLocaleString()方法是toString()方法的本地化版本,经常返回相同的值。

[1,2,3].toLocaleString() // '1,2,3'

如果某一项值是nullundefined,那么使用toLocaleString()或toString()方法返回值以空字符表示

[1,null,undefined, 2].toString() // '1,,,2'
[1,null,undefined, 2].toLocaleString() // '1,,,2'

valueOf()

valueOf()方法返回数组本身

[1,2,3].valueOf()  // [1,2,3]

转换方法

join()方法把数组转换为字符串,它是String.split()方法的逆向操作,split()是将字符串切割成数组。

join()方法接受一个参数,表示用作分隔符的字符串。

// 默认使用逗号分隔符
[1,2,3].join() // '1,2,3'

// 不使用分隔符
[1,2,3].join('') // '123'

// 空格作为分隔符
[1,2,3].join(' ') // '1 2 3'

实现字符串重复效果

function repeatString(str, n) {
  return new Array(n + 1).join(str)
}

repeatString('hi', 3) // 'hihihi'

类数组对象也可以使用join()方法

var arrLike = {0: 'a', 1: 'b', 2: 'c', length: 3}
Array.prototype.join.call(arrLike, '-') // 'a-b-c'

栈和队列方法

栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构,最新添加的项会最先被移除。栈中项的插入(又称推入)和移除(又称弹出)均发生在栈的顶部。JS提供了push()和pop()方法实现了类似栈的行为。

队列是一种FIFO(First-In-First-Out,先进先出)的数据结构,最先添加的项最先被移除。队列中项的插入和移除均发生在列表的底部。JS提供了unshift()和shift()方法实现了类似队列的行为。

push()

push()方法接收任何数量的参数,把它们添加到数组的末尾,返回修改后的数组长度。该操作改变原始数组。

var a = []
console.log(a, a.push('a','b','c')) // ['a','b','c'] 3

console.log(a, a.push(['d','e'])) // ['a','b','c',['d','e']] 4

push()方法也可以向对象中添加元素,对象会变成类数组对象。

var o = {name: 'hello'}
console.log(o, [].push.call(o, 'a', 'b')) // {0: "a", 1: "b", name: "hello", length: 2}

pop()

pop()方法从数组末尾移除最后一项,返回移除项。该操作改变原始数组。

var a = ['a', 'b', 'c']
console.log(a,a.pop()); // ['a', 'b'] 'c'

var a2 = []
console.log(a2,a2.pop()) // [] undefined

unshift()

unshift()方法接收任何数量的参数,把它们添加到数组的前端,返回修改后的数组长度。该操作改变原始数组。

var a = ['a', 'b', 'c']
console.log(a,a.unshift('x','y','z')) //['x','y','z','a', 'b', 'c'] 6

当有多个参数时,参数是一次向插入的,所以插入元素的顺序和参数的顺序一致。

shift()

shift()方法移除数组中的第一项,返回移除项。该操作改变原始数组。

var a = ['a','b','c']
console.log(a,a.shift()); // ['b', 'c'] 'a'

var a2 = []
console.log(a2,a2.shift()) // [] undefined

排序方法

数组中有sort()和reverse()两个排序方法,它们均改变原始数组

reverse()

reverse()方法反转原始数组的顺序,返回排序后的数组。

var arr = [1,2,3]
console.log(arr,arr.reverse()) // [3,2,1] [3,2,1]

sort()

sort()方法默认情况下按字符串升序排列数组项,每个数组项会调用toString()方法,通过比较得到的字符串进行排序,返回排序后的数组。

var a = [1,4,2,3]
console.log(a, a.sort()) // [1,2,3,4]

sort()方法接收一个函数作为参数,可以指定哪个值在哪个值前。函数接收两个参数,如果第一个参数应该位于第二个参数之前则返回一个负数,如果两个参数相等则返回0,如果第一个参数应该位于第二个参数之后则返回一个正数。

function compare(value1,value2){
   // 字符串比较需要统一大小写,这里统一小写
    var v1 = value1.toLowerCase(); 
    var v2 = value2.toLowerCase();
    if(v1 < v2){
        return -1;
    }else if(v1 > v2){
        return 1;
    }else{
        return 0;
    }
}
var arr = ['pig','Cat','dog'];
console.log(arr.sort(compare)); //  ["Cat", "dog", "pig"]

数值类型或valueOf()方法返回数值类型的对象类型,可以简化比较函数

function compare(value1,value2){
    return value1 - value2;
}

var arr = [5,1,3];
console.log(arr.sort()); // [1, 3, 5]

拼接方法

concat()方法可以接收任意个数参数,它会把参数添加到数组的末尾。如果参数是数组,它会把数组中的每一项添加到数组的末尾。该操作创建一个数组的副本,所以不会改变原始数组。

var a =[1,2,3]
console.log(a,a.concat(4,[5,6], [[7,8]])) // [1, 2, 3]  [1, 2, 3, 4, 5, 6, [7,8]]

如果不传递参数则返回一个数组的浅拷贝。
浅拷贝是指如果数组中包含复合类型值(如对象、数组),那么新数组拷贝的是该值的引用。

var a = [1,2]
var newArr = a.concat()
console.log(a,newArr) // [1,2] [1,2]

a[0] = 0
console.log(a,newArr) // [0,2] [1,2]


var a2 = [1, {num: 2}]
var newArr2 = a2.concat() 
console.log(a2,newArr2) // [1, {num: 2}] [1, {num: 2}]

a2[1].num = 3
console.log(a2,newArr2) // [1, {num: 3}] [1, {num: 3}]

concat()也可用于对象,把对象合并成数组

var o = {name: 'hello', age: 10}

console.log([].concat.call(o)) // [{name: "hello", age: 10}]

创建子数组

slice(start[,end])接收两个参数,返回字符串从start位置(不包括start位置处的字符)到end位置的一个子数组。如果end不存在,则end等于数组的长度值;如果start或end大于数组的长度,则start或end等于数组的长度。该操作不改变原始数组。

如果start是负数,start = arr.length + start
如果end是负数,end = arr.length + end

var arr = [1,2,3,4,5]

// 没有参数,返回原数组的浅拷贝
arr.slice() // [1,2,3,4,5]

arr.slice(2, 4) // [3,4]

arr.slice(-2) // [4,5]

slice()方法可用于类数组对象,把它变成数组

Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 })// ['a', 'b']

数组删改

splice()方法可以删改数组中的元素,并且可以在指定位置插入新的元素。该操作会改变原始数组。

splice()方法的第一个参数start表示删除操作的起始位置,当值为负数时start等于length + start。第二个参数表示删除元素的个数,当值为负数时相当于0,值是0时不会删除元素。第二个参数之后的更多参数表示要插入到数组中的元素,插入位置由第一个参数决定。最终会返回一个由删除元素组成的数组。

当只有一个参数时,会把数组在指定位置拆分成两个数组。

var a = [1,2,3,4,5]
console.log(a,a.splice()) // [1,2,3,4,5] []

console.log(a,a.splice(3)) // [1,2,3]  [4,5]

console.log(a,a.splice(-2)) // [1,2,3]  [4,5]

第二个参数表示删除元素的个数

var a = [1,2,3,4,5]

console.log(a,a.splice(3, 1)) // [1,2,3,5] [4]
console.log(a,a.splice(3, 0)) // [1,2,3,4,5] []

第三个以及之后更多参数都表示要添加的项

var a = [1,2,3,4,5]

console.log(a,a.splice(3, 0,'a','b')) // [1, 2, 3, "a", "b", 4, 5]  []
console.log(a,a.splice(3, 2,'a','b')) // [1, 2, 3, "a", "b"]  [4,5]

位置查询方法

ES5为数组实例增加了indexOf()和lastIndexOf()两个查询方法,

indexOf()

indexOf(search, start)方法接收两个参数,search表示搜索项,内部使用恒等运算符===进行比较。start表示搜索的起始位置,会自动调用Number()转型函数,当值为负数时start=length+start。该方法返回search首次出现的位置,如果找不到则返回-1。

var arr = ['a','b','c','b','d']
console.log(arr.indexOf('b')) // 1  a处(包含a)开始搜索
console.log(arr.indexOf('b', 2)) // 3  c处(包含c)开始搜索
console.log(arr.indexOf('b', -2)) // 3 第二个b处(包含b)开始搜索  5 + (-2) = 3
console.log(arr.indexOf('e')) // -1

lastIndexOf()

lastIndexOf(search, start)方法同indexOf()方法类似,不同的是该方法是从右至左执行查询。

var arr = ['a','b','c','b','d']
console.log(arr.lastIndexOf('b')) // 3  d处(包含d)开始搜索
console.log(arr.lastIndexOf('b', 2)) // 1 c处(包含c)开始搜索
console.log(arr.lastIndexOf('b', -2)) // 3  第二个b处(包含b)开始搜索
console.log(arr.lastIndexOf('e')) // -1

注意: 字符串也有indexOf()和lastIndexOf()方法,但是当start为负数时,两则有区别:字符串的这两个方法会把start当做0,而数组的start等于length + start

小技巧: 返回满足条件的所有索引项

function allIndexOf(array,value){
    var result = [];
    var pos = array.indexOf(value);
    if(pos === -1){
        return -1;
    }
    while(pos > -1){
        result.push(pos);
        pos = array.indexOf(value,pos+1);
    }
    return result;
}
var array = ['a','b','c','b','d'];
console.log(allIndexOf(array,'b'));//[1,3] 

数组归并

数组归并有reduce()和reduceRight()两个方法,它们均接受两个参数:第一个参数是函数,表示如何归并数组元素,它的任务就是使用某种方式把两个值组合成一个值,并返回组合后的值;第二个参数是可选的,表示传递给函数的初始化值。

第一个参数是函数,函数有四个参数,前两个必选,后两个可选:

  1. 初始变量,默认为数组的第一个元素。函数执行一次后的返回值作为第二次执行的初始化变量,以此类推。
  2. 当前变量
  3. 当前变量在数组中的索引
  4. 原始数组对象
values.reduce(function(prev, cur, index, array){
   //todo
});

第二个参数是传递给函数的初始化值。

var a = [1,2,3]
// 求和
var sum = a.reduce(function(prev, cur){ return prev + cur }, 0)
// 求乘积
var product = a.reduce(function(prev, cur){ return prev * cur }, 1)
// 求最大值
var max = a.reduce(function(prev, cur){ return (prev > cur) ? prev : cur })

console.log(sum) // 6
console.log(product) // 6
console.log(max) // 3

第二个参数的类型可以决定函数返回值的类型

var a = [1,2,3]
var sum = a.reduce(function(prev, cur){ 
    prev.sum = prev.sum + cur
    return prev
}, {sum: 0})
console.log(sum) // {sum: 6}

注意: 在空数组上使用reduce()方法,如果没有初始化参数的话会导致类型错误。当数组只有一个值且没有初始化参数,或者数组为空且有一个初始化参数时,reduce()方法只会返回那个值而不会调用函数。

var a = []
var sum = a.reduce(function(prev, cur){ return prev + cur }) // 报错
var sum2 = a.reduce(function(prev, cur){ return prev + cur }, 0) // 0

var a2 = [0]
var sum3 = a2.reduce(function(prev, cur){ return prev + cur }) // 0

应用:找出数组中最长的元素

var a = ['a', '123', 'ab', 'hello']
var maxEle = a.reduce(function(prev, cur){
    return prev.length > cur.length ? prev : cur
}, '')
console.log(maxEle) // 'hello'

应用:二维数组合并

var a = [['a','b'], ['c','d']]
var arr = a.reduce(function(prev, cur){
    return prev.concat(cur)
})
console.log(arr) // ["a", "b", "c", "d"]

reduceRight()方法和reduce()方法类似,不同的是该方法是从高到低(右到左)处理数组。

var a = [1,2,3]
var sum = a.reduceRight(function(prev,cur){
    console.log(prev,cur)
    return prev + cur
})

console.log(sum)
// 3 2
// 5 1
// 6

迭代方法

ES5为数组定义了5个迭代方法,每个方法都接收两个参数:第一个参数表示要在每一项上运行的函数;第二个参数是可选的,表示运行该函数的作用域对象,用于改变this值。第一个参数中的函数接收三个参数:数组项的值、该项的索引和数组对象本身。

map()

map()方法对数组中的每一项运行指定函数,最终返回一个由函数调用结果组成的数组

var ret = [1,2,3].map(function(item, index, array) {
return item * item
})
console.log(ret) // [1,4,9]

// 第二个参数改变this指向
var arr = ['a','b','c']
var ret2 = [1,2].map(function(item, index, array){
    return this[item]
}, arr)
console.log(ret2) // ['b','c']

日常开发中,该方法常用于获取对象数组中的指定属性

var data = [{name: 'li', age: 10}, {name: 'wang', age: 15}, {name: 'zhang', age: 5}]
var ret3 = data.map(function(item, index, array) {
return item.name
})
console.log(ret3) // ["li", "wang", "zhang"]

可以应用于类数组对象

var str = 'hello'
var ret = Array.prototype.map.call(str, function(item, index, arr) {
return item.toUpperCase()
})
console.log(ret) // ["H", "E", "L", "L", "O"]

稀疏数组中不存在的元素,不会调用该方法

var arr = [1,,3]
var ret = arr.map(function(item, index, arr){
    return item * 2
})
console.log(ret) // [2, empty, 6]

forEach()

forEach()方法对数组中的每一项运行指定函数,没有返回值。同使用for循环迭代数组效果一样。

[1,2,3].forEach(function(item,index,arr){
    console.log(item)
})
// 1
// 2
// 3

var arr = []
[1,2,3].forEach(function(item, index, arr){
   this.push(item * item)
}, arr)

console.log(arr) // [1,4,9]

对于多层嵌套的情况,this指向通常不一致,这时第二个参数很有用

var obj = {
name: 'wang',
likes: ['音乐', '编程', '阅读'],
test: function() {
    this.likes.forEach(function(item, index, arr){
    console.log(item)
    }, this)
  }
}
console.log(obj.test())
// 音乐
// 编程
// 阅读

forEach()循环可以用于类数组对象

var str = 'abc'
Array.prototype.forEach.call(str, function(item, index, array) {
  console.log(item)
})
//a
//b
//c

对于稀疏数组中不存在的元素,forEach()方法不会调用该方法,而for循环照样遍历。

var arr = [1,,3]
for(var i = 0; i < arr.length; i++){
    console.log(arr[i])
}
// 1
// undefined
// 3

arr.forEach(function(item, index, arr){
    console.log(item)
})
// 1
// 3

forEach()方法无法像for循环一样,在遍历过程中使用break语句终止遍历,会导致发生错误。

var arr = [1,2,3]
arr.forEach(function(item, index, arr){
    if(item === 2) break;
})
// Uncaught SyntaxError: Illegal break statement at Array.forEach

filter()

filter()方法对数组中的每一项运行指定函数,返回结果为true的项组成的数组。常用于筛选符合条件的数组项

[1, 2, 3, 4, 5].filter(function (item, index, arr) {
  return item % 2 === 0
}) // [2,4]

var min = [3];
var ret = [1, 2, 3, 4, 5].filter(function (item, index, arr) {
  return item > this[0]
}, min);// 
console.log(ret) // [4,5]

稀疏数组中的空元素会被过滤掉。

// 删除空缺、undefined和null元素
var arr = [1,2,,3,undefined,null]
var ret = arr.filter(function(item, index, arr){
    return item != undefined
})
console.log(ret) // [1,2,3]

some()

some()方法对数组中每一项运行指定函数,返回一个布尔值。当每项的执行结果都是false时才返回false,否则返回true。

var arr = [1,2,3]
arr.some(function(item, index, arr){
    return item > 2
})
// true

every()

every()方法对数组中每一项运行指定函数,返回一个布尔值。当每项的执行结果都是true时才返回true,否则返回false。

var arr = [1,2,3]
arr.every(function(item, index, arr){
    return item > 2
})
// false

结语

JavaScript中数组的方法是通用的,它们除了应用于数组外还可以应用于类数组对象。上面介绍的方法中除了toString()和toLocaleString()方法外,其他方法都是通用的。

可以改变原始数组的方法有七个:push()、 pup()、 unshift()、 shift()、 sort()、 reverse()、 splice()。

posted @ 2021-09-29 10:59  wmui  阅读(327)  评论(0编辑  收藏  举报