数组

141 阅读10分钟

js数组

数组有哪些原生方法?

  • 数组声明:new Array、字面量、Array.of
  • 数组检测:Array.isArray、instanceof、原型链、Object.prototype.toString.call()、Array.prototype.isPrototypeOf
  • 数组和字符串的转换方法:toString()、String()、toLocalString、join、split其中 join() 方法可以指定转换为字符串时的分隔符。
  • 数组尾部操作的方法 pop() 和 push(),均改变原数组,push返回数组元素数量,pop返回弹出的元素
  • 数组首部操作的方法 shift() 和 unshift() ,均改变原数组,unshift返回数组元素数量,shift返回弹出的元素
  • 重排序的方法 reverse() 和 sort(),sort() 方法可以传入一个函数来进行比较,传入前后两个值,如果返回值为正数,则交换两个参数的位置。
  • 数组连接的方法 concat() 、展开语法,返回的是拼接好的数组,不改变原数组。
  • 数组截取办法 slice(),用于截取数组中的一部分元素返回,不改变原数组,返回截取的新数组
  • 数组插入方法 splice(), 在任意位置添加、删除、替换,改变原数组,返回删除的元素
  • 查找特定元素的方法,indexOf、 lastIndexOf 、includes、find、findIndex
  • 迭代方法keys、values、entries、 every、some、filter、map 、reduce和 forEach 、for/in、for/of.

声明数组

1-Array.of

Array.ofnew Array 不同是设置一个参数时不会创建空元素数组

let hd = Array.of(3);
console.log(hd); //[3]

let hda = new Array(3);
console.log(hda); //['','','']

2-Array.isArray

检测变量是否为数组类型

console.log(Array.isArray([1, "后盾人", "hdcms"])); //true
console.log(Array.isArray(9)); //false

类型转换

1-数组转换字符串

(1).toString()

大部分数据类型都可以使用.toString() 函数转换为字符串。

console.log(([1, 2, 3]).toString()); // 1,2,3

(2)函数 String

也可以使用函数 String 转换为字符串。

console.log(String([1, 2, 3]));

(3)join

使用join连接为字符串

console.log([1, 2, 3].join("-"));//1-2-3

2-Array.from

(1)使用Array.from可将类数组转换为数组,类数组指包含 length 属性或可迭代的对象。

  • 第一个参数为要转换的数据,第二个参数为类似于map 函数的回调方法
let str = '后盾人';
console.log(Array.from(str)); //["后", "盾", "人"]
<body>
    <button message="后盾人">button</button>
    <button message="hdcms">button</button>
</body>

<script>
    let btns = document.querySelectorAll('button');
    console.log(btns); //包含length属性
    Array.from(btns, (item) => {
        item.style.background = 'red';
    });
</script>

展开语法

数组合并,函数参数,节点转换

解构赋值

1-数组结构

let [name, url] = ['后盾人', 'houdunren.com'];
console.log(name);  //后盾人

let [a, ...b] = ['后盾人', 'houdunren', 'hdcms'];
console.log(b);     //[ 'houdunren', 'hdcms' ]

2-字符串解构

const [...a] = "houdunren.com";
console.log(a); //Array(13)

3-设置默认值

let [name, site = 'hdcms'] = ['后盾人'];
console.log(site); //hdcms

管理元素

语法名元素位置数组是否改变返回值
push从后添加改变原数组数组元素数量
unshift从前添加改变原数组数组元素数量
pop从后弹出改变原数组弹出的元素
shift从前弹出改变原数组弹出的元素
中间元素
fill中间添加改变原数组原数组
slice截取元素不改变原数组截取的新数组
splice在任意位置添加、删除、替换改变原数组删除的元素

对数组前后元素的管理

1-push

  • 从后添加元素
  • 改变原数组
  • 返回值为数组元素数量
let arr = ["后盾人", "hdcms"];
console.log(arr.push(1, 2));   //4
console.log(arr);              //[ '后盾人', 'hdcms', 1, 2 ]

2-unshift

  • 从前添加元素
  • 改变原数组
  • 返回值为数组元素数量
let arr = ["后盾人", "hdcms"];
console.log(arr.unshift('向军大叔', 'houdunren')); //4
console.log(arr); //["向军大叔", "houdunren", "后盾人", "hdcms"]

3-pop

  • 从末尾弹出
  • 改变原数组
  • 返回值为弹出的元素
let arr = ["后盾人", "hdcms"];
console.log(arr.pop());       //hdcms
console.log(arr);             //["后盾人"]

4-shift

  • 从前弹出
  • 改变原数组
  • 返回值为弹出的元素
let arr = ["后盾人", "hdcms"];
console.log(arr.shift()); //后盾人
console.log(arr); //["hdcms"]

对数组中间元素的管理

5-fill

第一个参数为填充的内容,第二个为从哪里开始添加,第三个为添加到那个位置

  • 填充元素
  • 改变原数组
  • 返回值为原数组
let a = [1, 2, 3, "12"];
console.log(a.fill("后盾人", 2, 4));  //[ 1, 2, '后盾人', '后盾人' ]

6-slice

第一个参数为从哪里开始截取,第二个为截取的位置

  • 截取元素
  • 不改变原数组
  • 返回值为截取的元素组成的新数组
let arr = [0, 1, 2, 3, 4, 5, 6];
console.log(arr.slice(1, 3)); // [1,2]

let arr = [0, 1, 2, 3, 4, 5, 6];
console.log(arr.slice()); //[0, 1, 2, 3, 4, 5, 6]

7-splice

使用 splice 方法可以在数组的任意位置添加、删除、替换数组中的元素

  • 添加、删除、替换数组中的元素
  • 改变原数组
  • 返回值为删除的元素,没有删除的元素返回为空
let arr = [1, 2, 3, 4, 5];
let b = arr.splice(0, 2); //从第0个开始,截取几个元素                      相当于删除
let c = arr.splice(0, 0, "hou"); //从第0个开始,不截取元素,添加一个元素   相当于添加
let d = arr.splice(0, 1, "hd"); //从第0个开始,截取1个元素,添加一个元素  相当于替换
console.log(arr, b, c, d); //[ 'hd', 3, 4, 5 ] [ 1, 2 ] [] [ 'hou' ]

清空数组

将数组值修改为[]可以清空数组,如果有多个引用时数组在内存中存在被其他变量引用。

let user = [{ name: "hdcms" }, { name: "后盾人" }];
let cms = user;
user = [];
console.log(user);
console.log(cms);

合并拆分

1-join

使用join连接成字符串

let arr = [1, "后盾人", "hdcms"];
console.log(arr.join('-')); //1-后盾人-hdcms 使用join可以指定转换的连接方式

2-split

split 方法用于将字符串分割成数组,类似join方法的反函数。

let price = "99,78,68";
console.log(price.split(",")); //["99", "78", "68"]

3-concat

concat方法用于连接两个或多个数组

let array = ["hdcms", "houdunren"];
let hd = [1, 2];
let cms = [3, 4];
console.log(array.concat(hd, cms)); //["hdcms", "houdunren", 1, 2, 3, 4]
// 也可以使用扩展语法实现连接
console.log([...array, ...hd, ...cms]);

4-copyWithin

使用 copyWithin 从数组中复制一部分到同数组中的另外位置。

const arr = [1, 2, 3, 4];
//array.copyWithin(target, start, end)
console.log(arr.copyWithin(2, 0, 2)); //[1, 2, 1, 2]

查找元素

1-indexOf

使用 indexOf 从前向后查找元素出现的位置,找到返回元素索引,如果找不到返回 -1

let arr = [7, 3, 2, 8, 2, 6];
console.log(arr.indexOf('8')); // -1 indexOf 类似于===是严格类型约束。
console.log(arr.indexOf(2)); // 2 从前面查找2出现的位置

第二个参数用于指定查找开始位置

let arr = [7, 3, 2, 8, 2, 6];
//从第二个元素开始向后查找
console.log(arr.indexOf(2, 3)); //4

2-lastIndexOf

使用 lastIndexOf 从后向前查找元素出现的位置,如果找不到返回 -1

let arr = [7, 3, 2, 8, 2, 6];
console.log(arr.lastIndexOf(2)); // 4 从后查找2出现的位置

3-includes

使用 includes 查找字符串返回值是布尔类型更方便判断

let arr = [7, 3, 2, 6];
console.log(arr.includes(6)); //true

4-find

find 方法找到后会返回第一次找到的值,不继续查找,如果找不到返回值为undefined

let arr = ["hdcms", "houdunren", "hdcms"];

let find = arr.find(function(item) {
  return item == "hdcms";
});
console.log(find); //hdcms

使用includes等不能查找引用类型,因为它们的内存地址是不相等的,find 可以方便的查找引用类型

const user = [{ name: "李四" }, { name: "张三" }, { name: "后盾人" }];
const find = user.find(user => (user.name = "后盾人"));
console.log(find);

5-findIndex

findIndexfind 的区别是返回索引值,查找不到时返回 -1

let arr = [7, 3, 2, '8', 2, 6];

console.log(arr.findIndex(function (v) {
	return v == 8;                       //findindex和indexOf不同的是findindex是==非严格类型约束。
})); //3

数组排序

1-reverse

反转数组顺序,改变原数组

let arr = [1, 4, 2, 9];
console.log(arr.reverse()); //[9, 2, 4, 1]

2-sort

  • 返回负数 a 排在 b 前面,从小到大
  • 返回正数 b 排在 a 前面,从大到小
  • 返回 0 时不动

默认从小于大排序数组元素,改变原数组

let arr = [1, 4, 2, 9];
console.log(arr.sort()); //[1, 2, 4, 9]

使用排序函数从大到小排序,参数一与参数二比较,返回正数为降序负数为升序,改变原数组

let arr = [1, 4, 2, 9];
console.log(arr.sort(function (v1, v2) {
	return v2 - v1;
})); //[9, 4, 2, 1]

循环遍历

1-forEach

forEach使函数作用在每个数组元素上,没有返回值。

let lessons = [
  { title: "媒体查询响应式布局", category: "css" },
  { title: "FLEX 弹性盒模型", category: "css" },
  { title: "MYSQL多表查询随意操作", category: "mysql" },
];
lessons.forEach((item, index, array) => {
  console.log(item, index, array);
  //item  每个数组元素
  //index 每个索引
  //array 原数组
});

2-for/in

遍历时的 key 值为数组的索引

let lessons = [
	{title: '媒体查询响应式布局',category: 'css'},
  {title: 'FLEX 弹性盒模型',category: 'css'},
	{title: 'MYSQL多表查询随意操作',category: 'mysql'}
];

for (const key in lessons) {
    console.log(key);
}

3-for/of

每次循环取其中的值。

let lessons = [
  { title: "媒体查询响应式布局", category: "css" },
  { title: "FLEX 弹性盒模型", category: "css" },
  { title: "MYSQL多表查询随意操作", category: "mysql" },
];

for (const item of lessons) {
  console.log(item); // { title: "媒体查询响应式布局", category: "css" },
}

迭代器

const hd = ["houdunren", "hdcms"];
const keys = hd.keys();
console.log(keys.next());
console.log(keys.next());

1-keys

获取数组所有键

"use strict";
const arr = ["a", "b", "c", "后盾人"];

for (const key of arr.keys()) {
  console.log(key); //0 1 2 3 
}

2-values

获取数组的所有值

"use strict";
const arr = ["a", "b", "c", "后盾人"];

for (const value of arr.values()) {
  console.log(value);  //a ,  b ,  c ,  后盾人
}

3-entries

返回数组所有键值对,将keys和values的方法结合

const arr = ["a", "b", "c", "后盾人"];
for (const [key, value] of arr.entries()) {
  console.log(key, value);
}

数组扩展

1-every

every 用于递归的检测元素,要所有元素操作都要返回真结果才为真。

//查看班级中同学的 JS 成绩是否都及格
const user = [
  { name: "李四", js: 89 },
  { name: "马六", js: 65 },
  { name: "张三", js: 78 },
];
const result = user.every(function (item, index, arr) {
  if (item.name == "李四") {
    item.name = "李三";
  }
  return item.js >= 60;
});
console.log(result);

2-some

some 函数可以递归的检测元素,如果有一个返回 true,表达式结果就是真。

let words = ["后盾", "北京", "武汉"];
let title = "后盾人不断分享技术教程";

let state = words.some(function (item, index, array) {
  console.log(title.indexOf(item));
  return title.indexOf(item) >= 0;
});

if (state) console.log("标题含有违规关键词");

3-filter

使用 filter 可以过滤数据中元素,返回值为真被保留在新的数组,不会改变原数组。

let lessons = [
  { title: "媒体查询响应式布局", category: "css" },
  { title: "FLEX 弹性盒模型", category: "css" },
  { title: "MYSQL多表查询随意操作", category: "mysql" },
];
let cssLessons = lessons.filter(function (item, index, array) {
  if (item.category.toLowerCase() == "css") {
    return true;
  }
});
console.log(cssLessons);

4-map

使用 map 映射可以在数组的所有元素上应用函数,用于映射出新的值,直接改变原数组

let lessons = [
  { title: "媒体查询响应式布局", category: "css" },
  { title: "FLEX 弹性盒模型", category: "css" },
  { title: "MYSQL多表查询随意操作", category: "mysql" },
];
lessons = lessons.map(function (item, index, array) {
  item.title = `后盾人${item["title"]}`;
  return item;
});
console.log(lessons);

5-reduce

函数参数说明如下

参数说明
prev上次调用回调函数返回的结果
cur当前的元素值
index当前的索引
array原数组
//统计元素出现的次数
function countArrayELem(array, elem) {
  return array.reduce((total, cur) => (total += cur == elem ? 1 : 0), 0);
}

let numbers = [1, 2, 3, 1, 5];
console.log(countArrayELem(numbers, 1)); //2
//取数组中的最大值
function arrayMax(array) {
  return array.reduce(
  	(max, elem) => (max > elem ? max : elem), array[0]
  );
}

console.log(arrayMax([1, 3, 2, 9]));
//取价格最高的商品
let cart = [
  { name: "iphone", price: 12000 },
  { name: "imac", price: 25000 },
  { name: "ipad", price: 3600 }
];

function maxPrice(array) {
  return array.reduce(
    (goods, elem) => (goods.price > elem.price ? goods : elem),
    array[0]
  );
}
console.log(maxPrice(cart));
//计算购物车中的商品总价
let cart = [
  { name: "iphone", price: 12000 },
  { name: "imac", price: 25000 },
  { name: "ipad", price: 3600 }
];

const total = cart.reduce(
	(total, goods) => total += goods.price, 0
);
console.log(total); //40600
//获取价格超过 1 万的商品名称
let goods = [
  { name: "iphone", price: 12000 },
  { name: "imac", price: 25000 },
  { name: "ipad", price: 3600 }
];

function getNameByPrice(array, price) {
  return array.reduce((goods, elem) => {
    if (elem.price > price) {
      goods.push(elem);
    }
    return goods;
  }, []).map(elem => elem.name);
}
console.table(getNameByPrice(goods, 10000));
//使用 reduce 实现数组去重
let arr = [1, 2, 6, 2, 1];
let filterArr = arr.reduce((pre, cur, index, array) => {
  if (pre.includes(cur) === false) {
      pre = [...pre, cur];
  }
  return pre;
}, [])
console.log(filterArr); // [1,2,6]

原理

find 原理

下面使用自定义函数

let arr = [1, 2, 3, 4, 5];
function find(array, callback) {
  for (const value of array) {
    if (callback(value) === true) return value;
  }
  return undefined;
}
let res = find(arr, function(item) {
  return item == 23;
});
console.log(res);

下面添加原型方法实现

Array.prototype.findValue = function(callback) {
  for (const value of this) {
    if (callback(value) === true) return value;
  }
  return undefined;
};

let re = arr.findValue(function(item) {
  return item == 2;
});
console.log(re);

排序原理

let arr = [1, 5, 3, 9, 7];
function sort(array, callback) {
  for (const n in array) {
    for (const m in array) {
      if (callback(array[n], array[m]) < 0) {
        let temp = array[n];
        array[n] = array[m];
        array[m] = temp;
      }
    }
  }
  return array;
}
arr = sort(arr, function(a, b) {
  return a - b;
});
console.table(arr);