数组基本操作可以归纳为 增、删、改、查,需要留意的是哪些方法会对原数组产生影响,哪些方法不会
搜索筛查
import { ref, watch } from 'vue';
const inputModelVal = ref('');
const listData = ref([]);
const filteredList = ref([]);
// 监听输入框 newVal的变化,返回过滤新数组的值
const handleInpVal = (newVal) => {
filteredList.value = listData.value.filter(item => item.model.includes(newVal));
listData.value = filteredList.value;
};
watch(inputModelVal, (newVal, oldVal) => {
handleInpVal(newVal);
});
判断两个数组是否相等
let arr1 = [1, 2, 3]
let arr2 = [1, 2, 3]
function arraysAreEqual(arr1, arr2) {
return JSON.stringify(arr1) === JSON.stringify(arr2);
}
增加
push 改
[ ].push(item1,item2,,,) 方法接收任意数量的参数,并将它们添加到数组末尾,会改变原数组,返回新的数组长度
var arr = [1, 2, 3];
arr.push(123,456);
// arr => [1, 2, 3, 123,456]
unshift 改
[ ].unshift(item1,item2,,,) 在数组开头添加任意多个值,会改变原数组,返回新的数组长度
var arr = [ 2, 3, 4];
arr.unshift(0, 1);
// arr => [0, 1, 2, 3, 4]
splice 改
[ ].splice(index,0, ...) 传入三个参数,分别是开始位置、0(要删除的元素数量)、插入的元素,会改变原数组,返回被删除元素组成的数组
// 增,从第一个参数之后增加
var arr = [1, 5];
var arr1 = arr.splice(1, 0, 2, 3, 4);
// arr => [1, 2, 3, 4, 5]
// arr1 => []//返回值是被删除的元素组成的数组
concat
[ ].concat(arg1, arg2, arg3, ...) 拼接数组 。不会改变原数组,返回拼接之后的新数组
-
参数个数不定 如果参数中有数组 会把数组拆开,仅拆一次
var arr = [1, 2];
var arr1 = arr.concat(3, 4, 5, [6, 7, 8]);
// arr => [1, 2, 3, 4, 5, 6, 7, 8]
删除
pop 改
[ ].pop( ) ,不用传参数。用于删除数组的最后一项,同时减少数组的length
值,会改变原数组,返回被移除的成员
var arr = [1, 2, 3, 4];
var item = arr.pop();// 取得最后一项
// item => 4
// arr => [1, 2, 3]
shift 改
[ ].shift( ) ,不用传参数,用于删除数组的第一项,同时减少数组的length
值,会改变原数组,返回值是被移除的成员
var arr = [1, 2, 3, 4];
var item = arr.shift();// 取得第一项
// item => 1
// arr => [2, 3, 4]
splice 改
[ ].splice( index, 0 ) 当传入两个参数,分别是开始位置,删除元素的数量,会改变原数组,返回被删除元素组成的数组
let colors = ["red", "green", "blue"];
let removed = colors.splice(0,1); // 删除第一项
console.log(colors); // [green,blue]
console.log(removed); // red,只有一个元素的数组
// 删,删除包含第一个参数
var arr = [1, 2, 3, 4, 5];
var arr1 = arr.splice(1, 3);
// arr => [1, 5]
// arr1 => [2, 3, 4]
slice
[ ].slice( start, end ) 用于截取数组中的一段[包含, 不包含),不会改变原数组,返回截取之后的数组
第一个参数是开始截取的位置
第二个参数是结束截取的位置(不包含该位置的成员)
如果不传递第二个参数 则从第一个参数截取到最后
如果没有参数 就截取全部
如果参数是负数 则从后往前数
var arr = [11, 22, 33, 44];
// 两个参数
var arr1 = arr.slice(0, 3);
// arr => [11, 22, 33,44]
// arr1 => [11, 22, 33]
// 一个参数
var arr2 = arr.slice(2);
// arr2 => [33, 44]
// 没有参数
var arr4 = arr.slice();
// arr4 => [11, 22, 33, 44]
// 参数是负数
var arr3 = arr.slice(-1);
// arr3 => [44]
改变
即修改原来数组的内容,常用splice
splice 改
[ ].splice( start, del, add... ) splice 用于数组的增、删、改 。可传入三个参数。会改变原数组,返回值是删除元素的数组
第一个参数表示开始操作的位置
第二个参数表示删除的个数
第二个参数表示要插入的任意多个元素
如果没有第二个参数 则默认从第一个参数截取到末尾
// 增,从第一个参数之后增加
var arr = [1, 5];
var arr1 = arr.splice(1, 0, 2, 3, 4);
// arr => [1, 2, 3, 4, 5]
// arr1 => []//返回值是被删除的元素组成的数组
// 删,删除包含第一个参数
var arr = [1, 2, 3, 4, 5];
var arr1 = arr.splice(1, 3);
// arr => [1, 5]
// arr1 => [2, 3, 4]
// 改
let colors = ["red", "green", "blue"];
let removed = colors.splice(1, 1, "red", "purple"); // 插入两个值,删除一个元素
console.log(colors); // red,red,purple,blue
console.log(removed); // green,只有一个元素的数组
查
即查找元素,返回元素坐标或者元素值
indexOf
[ ].indexOf( item,start ) 用于搜索数组中的成员第一次出现时所在位置。不会改变原数组,返回值找到是下标位置,找不到就是 -1
第一个参数是数组成员
第二个参数是开始查找的下标,不传默认下标为 0
var arr = ["a", "b", "c"];
var idx = arr.indexOf("a");
// idx => 0
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
numbers.indexOf(4) // 3
includes
[ ].includes( item ) 接受一个参数 返回要查找的元素是否存在与数组中,找到返回true
,否则false
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
numbers.includes(4) // true
numbers.includes(6) // false
find
[ ].find(handler) 接受一个handler函数 用于以条件查询数组中首个匹配的成员。不会改变原数组,返回值找到是成员,找不到就是undefined
-
handler(item, index, arr) 函数 有三个参数
-
数组成员item
-
成员下标index
-
数组本身arr
-
返回布尔值 如果为真则停止循环并返回对应的成员,否则返回 undefined
-
var arr = ["浦东", "奉贤", "宝山", "青浦", "闵行", "徐汇"];
var baoshan = arr.find(function(value, index, arr) {
// console.log(value, index, arr);
return value.includes("山");
});
console.log(baoshan);
findIndex
[ ].findIndex(handler) 用于以条件查询数组中的成员首个匹配的下标,不会改变原数组,返回值找到是成员下标,找不到就是-1
-
handler(item, index, arr) 函数 有三个参数
-
数组成员item
-
成员下标index
-
数组本身arr
-
返回布尔值 如果为真则停止循环并返回对应的成员的下标,否则返回 -1
-
数组排序方法
reverse 改
[ ].reverse( ) 不用传递参数,将数组中的成员逆序排列。会把原数组改变,返回值是改变原数组的逆序
var arr = [1, 2, 3, 4, 5, 6];
var arr1 = arr.reverse();
// arr1 => [6, 5, 4, 3, 2, 1]
// arr => [6, 5, 4, 3, 2, 1]
sort 改
[ ].sort(a ,b) => 排序方法 方法接受一个比较函数,会把原数组改变,返回值是改变原数学组的排序
如果返回 a - b 升序排列,由小到大
如果返回 b - a 降序排列,由大到小
如果不传递函数 则按照首位数字进行排序
var arr = [10, 23, 44, 6, 88, 22];
// 升序
var arr1 = arr.sort(function(a, b) {
return a - b;
});
// arr => [6, 10, 22, 23, 44, 88]
// arr1 = > [6, 10, 22, 23, 44, 88]
// 降序
var arr2 = arr.sort(function(a, b) {
return b - a;
});
// arr => [88, 44, 23, 22, 10, 6]
转换方法
join
[ ].join()方法接收一个参数,即字符串分隔符,返回包含所有项的字符串。不会改变原数组,返回值是拼接完毕的字符串
-
参数是拼接符号 默认为逗号
,
var arr = ["a", "b", "c", "d"];
var str = arr.join();
// str => "a,b,c,d"
var str1 = arr.join("&");
// str1 => a&b&c&d
-
值得一提,字符串split方法 用分割符对原字符串,进行字符串分割,将分割完毕以后的子串,放在数组中返回。
cosnt str = 'a,b,c,d';
str.split(',') // ["a", "b", "c", "d"]
const str2 = 'a&b&c&d'
str.split('&') // ["a", "b", "c", "d"]
迭代方法
常用来迭代数组的方法(都不改变原数组)有如下:
some
some在数组中查找是否有符合条件的元素,对数组每一项都运行传入的函数,如果有一项函数返回 true ,则这个方法返回 true,所有项返回false才返回false
格式:[ ].some(function(item, index, arr){ return 形参关系式;})
返回值:有存在符合返回 true,没有返回 false。
短路操作:只要找到符合条件的元素,后面的循环就停止了。
var arr = [10, 20, 30, 40, 50];
var newArr = arr.some(function (item, index, arr) {
return item > 20;
}); //帅选的条件
console.log(newArr); //输出ture,但是程序遍历到30这个数,就已经跳出遍历循环了,所以40,50,压根不会遍历。
every
every对数组每一项都运行传入的函数,如果对每一项函数都返回 true ,则这个方法返回 true
格式:[ ].every(function(item, index, arr){ return > 形参关系式;})
返回值:全部都符合返回 true,否则返回 false。
短路操作:只要找到不符合条件的元素,后面的循环就停止了。
var arr = [10, 20, 30, 40, 50];
var newArr = arr.every(function (item, index, arr) {
return item > 20;
}); //筛选的条件
console.log(newArr); ///输出false,因为10>20是假的,所以程序遍历到10这个数,就已经跳出循环了。
filter
filter对数组中的每一运行给定的函数,会返回满足该函数的项组成的数组
格式:数组.filter(function(item, index, arr){ return > 形参关系式;})
返回值:将函数执行一次之后的返回一个符合过滤条件的数组。
var arr = [10, 20, 30, 40, 50];
var newArr = arr.filter(function (item, index, arr) {
return item > 20;
}); //过滤的条件
console.log(newArr); //[30,40,50]
map
map 映射,对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组
格式:数组.map(function(item, index, arr){ return 形参算术表达式;})
返回值:将函数执行一次之后的映射回一个满足条件的数组。
var arr = [2, 3, 4, 5, 6, 7];
// 映射出,全部加1的新数组
var newArr = arr.map(function (item, index, arr) {
return item + 1;
});
console.log(newArr); //[3, 4, 5, 6, 7, 8]
reduce
reduce(fn,初始值)
方法对数组中的每个元素执行一个由你提供的reducer函数(升序执行),将其结果汇总为单个返回值,
-
[ ].reduce(function(prev, item, index, arr){ return prev + item;},初始值)
-
prev 存在初始值时第一次是初始值;不存在初始值第一次是下标为 0 的元素;第二次开始上一次遍历 return 的值)
-
item 存在初始值下标从0开始,不存在初始值从下标 1 开始 表示即将遍历到的元素
-
index 当前遍历到元素的下标
-
arr 数组本身
-
-
返回值:归并的数组数据
var arr = [10, 20, 30, 40, 50];
var newArr = arr.reduce(function (prev, item) {
return prev + item;
}, 1);
console.log(newArr); //151 (就是将数组中的数据加起来,再加上初始值)
reduceRight() 与 reduce()的循环顺序相反,是从后往前,prev 变为最后一项。语法一致
forEach
对数组每一项都运行传入的函数,没有返回值
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
numbers.forEach((item, index, array) => {
// 执行某些操作
});
数组自带的foreach循环,使用频率较高,实际上性能比普通for循环弱
for...in
任意顺序遍历一个对象的除Symbol以外的可枚举属性,包括继承的可枚举属性。即for in 会遍历原型上的属性
一般常用来遍历对象,包括非整数类型的名称和继承的那些原型链上面的属性也能被遍历。像 Array和 Object使用内置构造函数所创建的对象都会继承自Object.prototype和String.prototype的不可枚举属性就不能遍历了.
var arr = [1,2,3,4,5]
for(var i in arr){
console.log(i,arr[i])
} //这里的i是对象属性,也就是数组的下标
/**
0 1
1 2
2 3
3 4
4 5 **/
大部分人都喜欢用这个方法,但它的性能却不怎么好
for...of(不能遍历对象)
在可迭代对象(具有 iterator 接口)(Array,Map,Set,String,arguments)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句,不能遍历对象
let arr=["前端","面试题宝典","真好用"];
for (let item of arr){
console.log(item)
}
//for...of..遍历对象会报错
let person={name:"前端面试题宝典",age:18,city:"上海"}
for (let item of person){
console.log(item)
}
// 我们发现它是不可以的 我们可以搭配Object.keys使用
for(let item of Object.keys(person)){
console.log(item, person[item])
}
这种方式是es6里面用到的,性能要好于for in,但仍然比不上普通for循环
for
标准的for循环语句,也是最传统的循环语句
var arr = [1,2,3,4,5]
for(var i=0;i<arr.length;i++){
console.log(arr[i])
}
最简单的一种遍历方式,也是使用频率最高的,性能较好,但还能优化
优化版for循环语句
var arr = [1,2,3,4,5]
for(var i=0,len=arr.length;i<len;i++){
console.log(arr[i])
}
使用临时变量,将长度缓存起来,避免重复获取数组长度,尤其是当数组长度较大时优化效果才会更加明显。
这种方法基本上是所有循环遍历方法中性能最高的一种
数组遍历各个方法的速度:传统的for循环最快,for-in最慢
for-len
>
for>
for-of>
forEach>
map>
for-in
javascript原生遍历方法的建议用法:
用
for
循环遍历数组用
for...in
遍历对象用
for...of
遍历类数组(ES6)用
Object.keys()
获取对象属性名的集合
字符串
我们也可将字符串常用的操作方法归纳为增、删、改、查,需要知道字符串的特点是一旦创建了,就不可变
增
这里增的意思并不是说直接增添内容,而是创建字符串的一个副本,再进行操作
除了常用+
以及${}
进行字符串拼接之外,还可通过concat
concat
用于将一个或多个字符串拼接成一个新字符串
let stringValue = "hello ";
let result = stringValue.concat("world");
console.log(result); // "hello world"
console.log(stringValue); // "hello"
删
这里的删的意思并不是说删除原字符串的内容,而是创建字符串的一个副本,再进行操作(获取字符串的指定部分)
常见的有:
slice[start, endIndex)第二个参数是提取的结束位置(直到,但不包括该结束位置的字符)
substring[start, endIndex),第二个参数是提取的结束位置(直到,但不包括该结束位置的字符)
substr[start, len),第二个参数是提取的字符数目
这三个方法都返回调用它们的字符串的一个子字符串,而且都接收一或两个参数。
let stringValue = "hello world";
console.log(stringValue.slice(3)); // "lo world"
console.log(stringValue.substring(3)); // "lo world"
console.log(stringValue.substr(3)); // "lo world"
console.log(stringValue.slice(3, 7)); // "lo w"
console.log(stringValue.substring(3,7)); // "lo w"
console.log(stringValue.substr(3, 7)); // "lo worl"
改
这里改的意思也不是改变原字符串,而是创建字符串的一个副本,再进行操作
常见的有:
trim()、trimLeft()、trimRight()
repeat()
padStart()、padEnd()
toLowerCase()、 toUpperCase()
trim()、trimLeft()、trimRight()
删除前、后或前后所有空格符,再返回新的字符串
let stringValue = " hello world ";
let trimmedStringValue = stringValue.trim();
console.log(stringValue); // " hello world "
console.log(trimmedStringValue); // "hello world"
repeat()
接收一个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果
let stringValue = "na ";
let copyResult = stringValue.repeat(2) // na na
padStart(),padEnd()
复制字符串,如果小于指定长度,则在相应一边填充字符,直至满足长度条件
let stringValue = "foo";
console.log(stringValue.padStart(6)); // " foo"
console.log(stringValue.padStart(9, ".")); // "......foo"
console.log(stringValue.padEnd(6)); // " foo "
console.log(stringValue.padEnd(9, ".")); // "foo......"
toLowerCase()、 toUpperCase()
大小写转化
let stringValue = "hello world";
console.log(stringValue.toUpperCase()); // "HELLO WORLD"
console.log(stringValue.toLowerCase()); // "hello world"
查
除了通过索引的方式获取字符串的值,还可通过:
chatAt(),由下标找字符串
indexOf(),由字符串找下标
startWith(),查询字符串是否存在,布尔值
includes(),查询字符串是否存在,布尔值
charAt(),返回给定索引位置的字符,由传给方法的整数参数指定
let message = "abcde";
console.log(message.charAt(2)); // "c"
indexOf()
从字符串开头去搜索传入的字符串,并返回位置(如果没找到,则返回 -1 )
let stringValue = "hello world";
console.log(stringValue.indexOf("o")); // 4
startWith()、includes()
从字符串中搜索传入的字符串,并返回一个表示是否包含的布尔值
let message = "foobarbaz";
console.log(message.startsWith("foo")); // true
console.log(message.startsWith("bar")); // false
console.log(message.includes("bar")); // true
console.log(message.includes("qux")); // false
二、转换方法
split
把字符串按照指定的分割符,拆分成数组中的每一项
let str = "12+23+34"
let arr = str.split("+") // [12,23,34]
三、模板匹配方法
针对正则表达式,字符串设计了几个方法:
match()
search()
replace()
match()
接收一个参数,可以是一个正则表达式字符串,也可以是一个RegExp
对象,返回数组
let text = "cat, bat, sat, fat";
let pattern = /.at/;
let matches = text.match(pattern);
console.log(matches[0]); // "cat"
search()
接收一个参数,可以是一个正则表达式字符串,也可以是一个RegExp
对象,找到则返回匹配索引,否则返回 -1
let text = "cat, bat, sat, fat";
let pos = text.search(/at/);
console.log(pos); // 1
replace()
接收两个参数,第一个参数为匹配的内容,第二个参数为替换的元素(可用函数)
let text = "cat, bat, sat, fat";
let result = text.replace("at", "ond");
console.log(result); // "cond, bat, sat, fat"
escape, encodeURI, encodeURIComponent使用场景
escape
具体规则是,除了ASCII字母、数字、标点符号"@ * _ + - . /"以外,对其他所有字符进行编码
这个方法是针对字符串使用的,不适用于URL。
encodeURI
Javascript中真正用来对URL编码的函数。它着眼于对整个URL进行编码,因此除了常见的符号以外,对其他一些在网址中有特殊含义的符号"; / ? : @ & = + $ , #",也不进行编码。编码后,它输出符号的utf-8形式,并且在每个字节前加上%。解码函数decodeURI()
encodeURIComponent
encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。
因此,"; / ? : @ & = + $ , #",这些在encodeURI()中不被编码的符号,在encodeURIComponent()中统统会被编码。至于具体的编码方法,两者是一样。解码函数decodeURIComponent()
var param = "http://www.cnblogs.com/season-huang/"; //param为参数
param = encodeURIComponent(param);
var url = "http://www.cnblogs.com?next=" + param;
console.log(url) //"http://www.cnblogs.com?next=http%3A%2F%2Fwww.cnblogs.com%2Fseason-huang%2F"
参数中的 "/" 可以编码,如果用encodeURI肯定要出问题,因为后面的/是需要编码的