Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript 基础系列之数组原生方法梳理 #98

Open
yuanyuanbyte opened this issue Nov 23, 2021 · 0 comments
Open

JavaScript 基础系列之数组原生方法梳理 #98

yuanyuanbyte opened this issue Nov 23, 2021 · 0 comments

Comments

@yuanyuanbyte
Copy link
Owner

yuanyuanbyte commented Nov 23, 2021

本系列的主题是 JavaScript 基础,每期讲解一个技术要点。如果你还不了解各系列内容,文末点击查看全部文章,点我跳转到文末

如果觉得本系列不错,欢迎 Star,你的支持是我创作分享的最大动力。

JS 数组有哪些原生方法,那么多 API 真的很难记住吗?

前言

通过梳理数组 API 的方式,归纳整理,你会发现 js 数组的方法并没有很难记住,一起来学习吧~

提醒一下大家,不要看到目录里那么多的数组方法就望而却步,一定要先看完数组原生方法梳理,了解数组到底有哪些方法,然后再逐个学习,这样你就会突然发现,其实数组也没多少方法嘛 ~ 都是能用到的

数组原生方法梳理

数组 判断方法Array.isArray()

数组 合并的方法concat(),返回的是拼接好的数组,不影响原数组。

数组和字符串的转换方法:toString()join(), 其中 join() 方法可以指定转换为字符串时的分隔符。

数组 尾部操作的方法: pop()push()push() 方法可以传入多个参数。

数组 首部操作的方法: shift()unshift()

数组 重排序的方法: reverse()sort()sort() 方法可以传入一个函数来进行比较,传入前后两个值,如果返回值为正数,则b 会被排列到 a 之前;如果返回值为负数, a 会被排列到 b 之前。

数组 截取办法: slice(),用于截取数组中的一部分,返回一个新的数组对象,不影响原数组。arr.slice(begin, end)slice 会提取原数组中索引从 beginend 的所有元素(包含 begin,但不包含 end)。 注意 ❗ ❗ ❗ slice()方法是浅拷贝,具体在下文做解释。

数组 删除、替换或插入方法splice(),通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容 (注意不是整个数组)。此方法会改变原数组。

数组 元素查找方法indexOf() includes()find()findIndex()

数组 迭代方法forEach()map()filter()every()some()

数组 归并方法reduce()

数组 扁平化方法flat()

Array.isArray() 数组判断

Array.isArray() 用于确定传递的值是否是一个 Array。

Array.isArray([1, 2, 3]);
// true
Array.isArray({foo: 123});
// false
Array.isArray("foobar");
// false
Array.isArray(undefined);
// false

instanceof 和 isArray

当检测Array实例时, Array.isArray 优于 instanceof,因为Array.isArray能检测iframes.

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]

// Correctly checking for Array
Array.isArray(arr);  // true
// Considered harmful, because doesn't work though iframes
arr instanceof Array; // false

concat() 数组合并

concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

合并两个数组

const array1 = ['a', 'b', 'c'];
const array2 = ['d', 'e', 'f'];
const array3 = array1.concat(array2);

console.log(array3);// Array ["a", "b", "c", "d", "e", "f"]

合并三个数组

以下代码将三个数组合并为一个新数组:

var num1 = [1, 2, 3],
    num2 = [4, 5, 6],
    num3 = [7, 8, 9];

var nums = num1.concat(num2, num3);

console.log(nums);// [1, 2, 3, 4, 5, 6, 7, 8, 9]

join() 数组和字符串的转换

join() 方法 将数组转换为字符串,并指定所有元素之间的分隔符。

const elements = ['Fire', 'Air', 'Water'];

console.log(elements.join()); // "Fire,Air,Water"

console.log(elements.join('')); // "FireAirWater"

console.log(elements.join('-')); // "Fire-Air-Water"

数组尾部操作

pop()

pop()方法 删除数组最后一个元素,并返回该元素的值。此方法更改数组的长度。

const plants = ['broccoli', 'cauliflower', 'cabbage', 'kale', 'tomato'];

console.log(plants.pop()); // "tomato"

console.log(plants); // Array ["broccoli", "cauliflower", "cabbage", "kale"]

plants.pop();

console.log(plants); //Array ["broccoli", "cauliflower", "cabbage"]

push()

push() 方法 将一个或多个元素添加到数组的末尾,并返回该数组的新长度。

const animals = ['pigs', 'goats', 'sheep'];

const count = animals.push('cows');
console.log(count); // 4
console.log(animals); // Array ["pigs", "goats", "sheep", "cows"]

animals.push('chickens', 'cats', 'dogs');
console.log(animals); // Array ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"]

数组首部操作

shift()

shift() 方法 删除数组第一个元素,并返回该元素的值。此方法更改数组的长度。

const array1 = [1, 2, 3];

const firstElement = array1.shift();

console.log(array1); // Array [2, 3]

console.log(firstElement); // 1

unshift()

unshift() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。

const array1 = [1, 2, 3];

console.log(array1.unshift(4, 5)); // 5

console.log(array1); // Array [4, 5, 1, 2, 3]

数组重排序

reverse() [rɪˈvɜrs]

reverse() 方法将数组中元素的位置颠倒,并返回该数组。该方法会改变原数组。

let a = [1, 2, 3, 4, 5];
a.reverse();
console.log(a); // (5) [5, 4, 3, 2, 1]

sort()

sort() 方法可以传入一个函数对数组的元素进行排序,传入a,b前后两个值,如果返回值为正数,则b 会被排列到 a 之前;如果返回值为负数, a 会被排列到 b 之前。

如果没有指明 排序算法,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。例如 "Banana" 会被排列到 "cherry" 之前。当数字按由小到大排序时,9 出现在 80 之前,但因为(没有指明 compareFunction),比较的数字会先被转换为字符串,所以在Unicode顺序上 "80" 要比 "9" 要靠前。

不指明 排序算法的用法:

const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);// Array ["Dec", "Feb", "Jan", "March"]

const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);// Array [1, 100000, 21, 30, 4]

指明 排序算法的用法:

可以用简单的写法比较数字:

var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
  return a - b;
});
console.log(numbers); // [1, 2, 3, 4, 5]

也可以写成:
var numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 2, 3, 4, 5]

可以按照对象的某个属性排序:

var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic' },
  { name: 'Zeros', value: 37 }
];

// sort by value
items.sort(function (a, b) {
  return (a.value - b.value)
});
console.log(items);// [
							{"name": "The","value": -12},
							{"name": "Edward","value": 21},
							{"name": "Sharpe","value": 37},
							{"name": "And","value": 45},
							{"name": "Magnetic"},
							{"name": "Zeros","value": 37}
					   ]

compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的,比如上面比较函数的输出结果,对value属性的排序结果是不确定的。

所以,如果我们按照对象的某个属性排序,需要确保对象的属性值存在:

var items = [
	{name: 'Edward',value: 21},
	{name: 'Sharpe',value: 37},
	{name: 'And',value: 45},
	{name: 'The',value: -12},
	{name: 'Magnetic',value: 100},
	{name: 'Zeros',value: 37}
];

// sort by value
items.sort(function (a, b) {
    return (b.value - a.value)
    // 注意,这次把 a.value - b.value 改为了b.value - a.value
    // 变成倒序了
});
console.log(items);// [
							{"name": "Magnetic","value": 100},
							{"name": "And","value": 45},
							{"name": "Sharpe","value": 37},
							{"name": "Zeros","value": 37},
							{"name": "Edward","value": 21},
							{"name": "The","value": -12}
						]

slice() [slaɪs] 数组截取 ✨

slice(),用于截取数组中的一部分,返回一个新的数组对象,不影响原数组。

注意 ❗ ❗ ❗ slice()方法是浅拷贝,具体在下文做解释。

arr.slice(begin, end)slice 会提取原数组中索引从 beginend 的所有元素(包含 begin,但不包含 end)。

begin 可选 是提取起始处的索引(从 0 开始),从该索引开始提取原数组元素。

  • 如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。

  • 如果省略 begin,则 slice 从索引 0 开始。

  • 如果 begin 超出原数组的索引范围,则会返回空数组。

end 可选 是提取终止处的索引(从 0 开始),在该索引处结束提取原数组元素。slice 会提取原数组中索引从 begin 到 end 的所有元素(包含 begin,但不包含 end)。

  • slice(1,4) 会提取原数组中从第二个元素开始一直到第四个元素的所有元素 (索引为 1, 2, 3的元素)。

  • 如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。 slice(-2,-1) 表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。

  • 如果 end 被省略,则 slice 会一直提取到原数组末尾。

  • 如果 end 大于数组的长度,slice 也会一直提取到原数组末尾。

❗ ❗ ❗ slice()方法的浅拷贝

slice 不会修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。原数组的元素会按照下述规则拷贝:

  • 如果该元素是个对象引用 (不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。
  • 对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。

如果向两个数组任一中添加了新元素,则另一个不会受到影响。

下面通过实例详细了解一下 slice()方法的浅拷贝:

下面的代码描述了修改数组的几种情况:

let menuTreeList = [{
                "id": "cfda8029dfb311e7b555201a068c6482",
                "name": "系统管理",
                "menuType": 0,
                "children": [{
                    "id": "3873ccc2dfda11e7b555201a068c6483",
                    "name": "菜单管理",
                    "menuType": 2,
                    "children": [{
                            "id": "18bf8d5df09511e78a57201a068c6484",
                            "name": "新增",
                            "menuType": 1
                        },
                        {
                            "id": "18bf8d5df09511e78a57201a068c6485",
                            "name": "修改",
                            "menuType": 1
                        }
                    ]
                }]
            },
            {
                "id": "cfda8029dfb311e7b555201a068c6486",
                "name": "设备管理",
                "menuType": 0,
                "children": [{
                        "id": "18bf8d5df09511e78a57201a068c6487",
                        "name": "新增",
                        "menuType": 1
                    },
                    {
                        "id": "18bf8d5df09511e78a57201a068c6488",
                        "name": "修改",
                        "menuType": 1
                    }
                ]
            }
        ]

 let a = menuTreeList.slice(0, 1);
 console.group("1.修改对象深层属性")
 // console.log('a :>> ', a);
 // 1.被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变:
 //   修改原始值 menuTreeList[0] ,即修改对象的引用
 menuTreeList[0].children = [];
 // 验证: 
 // 原来的数组:
 console.log('被修改过的原来的数组 menuTreeList :>> ', menuTreeList);
 // slice方法产生的新数组:
 console.log('新的数组 a :>> ', a);
 console.groupEnd()



 let newArr = [1, 2, 3, 4, 5, 6];
 let b = newArr.slice(0, 4);
 console.group("2.验证数组元素为字符串、数字及布尔值时的情况")
 // console.log('b :>> ', b);
 // 2.对于字符串、数字及布尔值来说,slice 会拷贝这些值到新的数组里。
 //   在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组:
 newArr[0] = 0;
 newArr[1] = 0;
 newArr[2] = 0;
 newArr[3] = 0;
 // 原来的数组:
 console.log('被修改过的原来的数组 newArr :>> ', newArr);
 // slice方法产生的新数组:
 console.log('新的数组 b :>> ', b);
 console.groupEnd();



 let newArr3 = [{
     "id": "1",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "2",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "3",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "4",
     "name": "设备管理",
     "menuType": 0,
 }];

 let d = newArr3.slice(0, 3);
 console.group("3.修改简单对象的属性 验证")
 // console.log('d :>> ', d);
 newArr3[0].id = "111111111";
 newArr3[1].id = "111111111";
 newArr3[2].id = "111111111";
 // 原来的数组:
 console.log('被修改过的原来的数组 newArr3 :>> ', newArr3);
 // slice方法产生的新数组:
 console.log('新的数组 d :>> ', d);
 console.groupEnd();



 let newArr2 = [{
     "id": "1",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "2",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "3",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "4",
     "name": "设备管理",
     "menuType": 0,
 }];
 let c = newArr2.slice(0, 3);
 console.group("4.把数组简单对象置空 验证")
 // console.log('c :>> ', c);
 newArr2[0] = {};
 newArr2[1] = {};
 newArr2[2] = {};
 // 原来的数组:
 console.log('被修改过的原来的数组 newArr2 :>> ', newArr2);
 // slice方法产生的新数组:
 console.log('新的数组 c :>> ', c);
 console.groupEnd()



 let newArr4 = [{
     "id": "1",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "2",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "3",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "4",
     "name": "设备管理",
     "menuType": 0,
 }];

 let e = newArr4.slice(0, 3);
 console.group("5.把数组简单对象元素改为基本数据类型 验证")
 newArr4[0] = 0;
 newArr4[1] = 0;
 newArr4[2] = 0;
 // 原来的数组:
 console.log('被修改过的原来的数组 newArr4 :>> ', newArr4);
 // slice方法产生的新数组:
 console.log('新的数组 e :>> ', e);
 console.groupEnd()

输出结果:

在这里插入图片描述

在这里插入图片描述

为什么把数组简单对象元素改为基本数据类型把数组简单对象置空这两种情况下的数组都没有跟着改变呢?

这个问题我是向 CSDN博客专家「零一」学习的,字节跳动大佬,很多高质量原创文章,快来观摩👉✨「零一」✨👈

问题解析:

我们可以这样立即,[q, w, e],其实这个数组中第一个元素就是变量q,那么他指向的是一个对象,

  • 如果修改该对象内部的属性,那么变量q仍然只是指向这个对象,对象的内存地址没变
  • 如果直接把数组中第一个元素修改为空对象,那么就相当于 q = {},那指向的肯定跟原来的不一样了

即原来数组里的元素改为了新的对象,使用了新的对象引用,新数组里的元素对象依然存储在堆里,使用的是旧的对象引用。

我们接着看下面这个例子:

  let newArr6 = [{
      "id": "1",
      "name": "设备管理",
      "menuType": 0,
  }, {
      "id": "2",
      "name": "设备管理",
      "menuType": 0,
  }, {
      "id": "3",
      "name": "设备管理",
      "menuType": 0,
  }, {
      "id": "4",
      "name": "设备管理",
      "menuType": 0,
  }];

  let f = newArr6.slice(0, 3);
  console.group("6.把数组简单对象设置为新的对象 验证")
  // console.log('c :>> ', c);

  newArr6[0] = {
      "sss": "4444",
      "aaaa": "对方是否",
  };
  newArr6[1] = {
      "sss": "4444",
      "aaaa": "对方是否",
  };;
  newArr6[2] = {
      "sss": "4444",
      "aaaa": "对方是否",
  };;

  // 原来的数组:
  console.log('被修改过的原来的数组 newArr6 :>> ', newArr6);
  // slice方法产生的新数组:
  console.log('新的数组 f :>> ', f);
  console.groupEnd()

输出结果:

在这里插入图片描述

其实不管是把对象改为基本数据类型,还是重新赋一个新的对象,他们都属于一类,都是修改了对象的指向

这里和基本的对象引用赋值做一个对比:

let menuTreeList = [{
         "id": "cfda8029dfb311e7b555201a068c6482",
         "name": "系统管理",
         "menuType": 0,
         "children": [{
             "id": "3873ccc2dfda11e7b555201a068c6483",
             "name": "菜单管理",
             "menuType": 2,
             "children": [{
                     "id": "18bf8d5df09511e78a57201a068c6484",
                     "name": "新增",
                     "menuType": 1
                 },
                 {
                     "id": "18bf8d5df09511e78a57201a068c6485",
                     "name": "修改",
                     "menuType": 1
                 }
             ]
         }]
     },
     {
         "id": "cfda8029dfb311e7b555201a068c6486",
         "name": "设备管理",
         "menuType": 0,
         "children": [{
                 "id": "18bf8d5df09511e78a57201a068c6487",
                 "name": "新增",
                 "menuType": 1
             },
             {
                 "id": "18bf8d5df09511e78a57201a068c6488",
                 "name": "修改",
                 "menuType": 1
             }
         ]
     }
 ]

 let a = menuTreeList;
 console.group("1.修改对象深层属性")
 menuTreeList[0].children = [];
 // 验证: 
 // 原来的数组:
 console.log('被修改过的原来的数组 menuTreeList :>> ', menuTreeList);
 console.log('新的数组 a :>> ', a);
 console.groupEnd()



 let newArr = [1, 2, 3, 4, 5, 6];

 let b = newArr;
 console.group("2.验证数组元素为字符串、数字及布尔值时的情况")
 newArr[0] = 0;
 newArr[1] = 0;
 newArr[2] = 0;
 newArr[3] = 0;

 // 原来的数组:
 console.log('被修改过的原来的数组 newArr :>> ', newArr);
 console.log('新的数组 b :>> ', b);
 console.groupEnd();



 let newArr3 = [{
     "id": "1",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "2",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "3",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "4",
     "name": "设备管理",
     "menuType": 0,
 }];

 let d = newArr3;
 console.group("3.修改简单对象的属性 验证")
 newArr3[0].id = "111111111";
 newArr3[1].id = "111111111";
 newArr3[2].id = "111111111";

 // 原来的数组:
 console.log('被修改过的原来的数组 newArr3 :>> ', newArr3);
 console.log('新的数组 d :>> ', d);
 console.groupEnd();

 let newArr2 = [{
     "id": "1",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "2",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "3",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "4",
     "name": "设备管理",
     "menuType": 0,
 }];

 let c = newArr2;
 console.group("4.把数组简单对象置空 验证")
 newArr2[0] = {};
 newArr2[1] = {};
 newArr2[2] = {};

 // 原来的数组:
 console.log('被修改过的原来的数组 newArr2 :>> ', newArr2);
 console.log('新的数组 c :>> ', c);
 console.groupEnd()


 let newArr4 = [{
     "id": "1",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "2",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "3",
     "name": "设备管理",
     "menuType": 0,
 }, {
     "id": "4",
     "name": "设备管理",
     "menuType": 0,
 }];

 let e = newArr4;
 console.group("5.把数组简单对象元素改为基本数据类型 验证")

 newArr4[0] = 0;
 newArr4[1] = 0;
 newArr4[2] = 0;

 // 原来的数组:
 console.log('被修改过的原来的数组 newArr4 :>> ', newArr4);
 console.log('新的数组 e :>> ', e);
 console.groupEnd()

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

splice() [splaɪs] 数组删除、替换或插入

splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。

语法:

array.splice(start, deleteCount, item1, item2, ...)

start​ 指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于array.length-n);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。

deleteCount 可选 整数,表示要移除的数组元素的个数。

  • 如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)。
  • 如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除。
  • 如果 deleteCount0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素。

item1, item2, ... 可选 要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。

由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。

如果添加进数组的元素个数不等于被删除的元素个数,数组的长度会发生相应的改变。

示例:

** 数组 插入元素,从索引 2 的位置开始删除 0 个元素,插入“drum”**

var myFish = ["angel", "clown", "mandarin", "sturgeon"];
var removed = myFish.splice(2, 0, "drum");

// 运算后的 myFish: ["angel", "clown", "drum", "mandarin", "sturgeon"]
// 被删除的元素: [], 没有元素被删除

** 数组 删除元素,从索引 3 的位置开始删除 1 个元素**

var myFish = ['angel', 'clown', 'drum', 'mandarin', 'sturgeon'];
var removed = myFish.splice(3, 1);

// 运算后的 myFish: ["angel", "clown", "drum", "sturgeon"]
// 被删除的元素: ["mandarin"]

** 数组 替换元素,索引 2 的位置开始删除 1 个元素,插入“trumpet”**

var myFish = ['angel', 'clown', 'drum', 'sturgeon'];
var removed = myFish.splice(2, 1, "trumpet");

// 运算后的 myFish: ["angel", "clown", "trumpet", "sturgeon"]
// 被删除的元素: ["drum"]

** 数组 替换元素,从索引 0 的位置开始删除 2 个元素,插入"parrot"、"anemone"和"blue"**

var myFish = ['angel', 'clown', 'trumpet', 'sturgeon'];
var removed = myFish.splice(0, 2, 'parrot', 'anemone', 'blue');

// 运算后的 myFish: ["parrot", "anemone", "blue", "trumpet", "sturgeon"]
// 被删除的元素: ["angel", "clown"]

** 数组 删除某索引后的所有元素,从索引 2 的位置开始删除所有元素**

var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var removed = myFish.splice(2);

// 运算后的 myFish: ["angel", "clown"]
// 被删除的元素: ["mandarin", "sturgeon"]

数组查找指定元素

indexOf()

indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。

indexOf()使用严格相等(strict equality,即 ===)比较 searchElement 和数组中的元素。

语法:

arr.indexOf(searchElement, fromIndex)

searchElement 要查找的元素

fromIndex 可选 开始查找的位置。

** 找出指定元素出现的所有位置 (注意,是所有元素,一个元素在数组中可能出现多次)**

var indices = [];
var array = ['a', 'b', 'a', 'c', 'a', 'd'];
var element = 'a';
var idx = array.indexOf(element);
while (idx != -1) {
  indices.push(idx);
  idx = array.indexOf(element, idx + 1);
}
console.log(indices);
// [0, 2, 4]

可以用于判断一个元素是否在数组里

lastIndexOf()

lastIndexOf() 方法返回指定元素在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始。

lastIndexOf 使用严格相等(strict equality,即 ===)比较 searchElement 和数组中的元素。

includes()

includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false

const array1 = [1, 2, 3];

console.log(array1.includes(2));// true

const pets = ['cat', 'dog', 'bat'];

console.log(pets.includes('cat'));// true

console.log(pets.includes('at'));// false

find()

find()方法对数组中的每一项元素执行一次 callback 函数,直至有一个 callback 返回 true。当找到了这样一个元素后,该方法会立即返回这个元素的值,否则返回 undefined

const array1 = [5, 12, 8, 130, 44];

const found = array1.find(element => element > 10);// 12

用对象的属性查找数组里的对象

var inventory = [
    {name: 'apples', quantity: 2},
    {name: 'bananas', quantity: 0},
    {name: 'cherries', quantity: 5}
];

function findCherries(fruit) {
    return fruit.name === 'cherries';
}

console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }

findIndex()

findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1。

const array1 = [5, 12, 8, 130, 44];

const isLargeNumber = (element) => element > 13;

console.log(array1.findIndex(isLargeNumber));// 3

数组迭代

forEach()

forEach() 方法对数组的每个元素执行一次给定的函数。

const array1 = ['a', 'b', 'c'];

array1.forEach(element => console.log(element));

// expected output: "a"
// expected output: "b"
// expected output: "c"

将 for 循环转换为 forEach

const items = ['item1', 'item2', 'item3'];
const copy = [];

// before
for (let i=0; i<items.length; i++) {
  copy.push(items[i]);
}

// after
items.forEach(function(item){
  copy.push(item);
});

扁平化数组

下面的示例仅用于学习目的。如果你想使用内置方法来扁平化数组,你可以考虑使用 Array.prototype.flat()(预计将成为 ES2019 的一部分,并且已在主要浏览器中实现)

/**
 * Flattens passed array in one dimensional array
 *
 * @params {array} arr
 * @returns {array}
 */
function flatten(arr) {
  const result = [];

  arr.forEach((i) => {
    if (Array.isArray(i))
      result.push(...flatten(i));
    else
      result.push(i);
  })

  return result;
}

// Usage
const problem = [1, 2, 3, [4, 5, [6, 7], 8, 9]];

flatten(problem); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

map()

map() 方法创建一个新数组,该方法会给原数组中的每个元素都按顺序调用一次 callback 函数。返回一个由原数组每个元素执行回调函数的结果组成的新数组

const array1 = [1, 4, 9, 16];

// pass a function to map
const map1 = array1.map(x => x * 2);

console.log(map1);
// expected output: Array [2, 8, 18, 32]

filter()

filter() 方法创建一个新数组,该方法为数组中的每个元素调用一次 callback 函数,并且将所有使 callback 返回 true等价于 true 的值 的元素创建一个新数组

filter 不会改变原数组,它返回过滤后的新数组。

const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]

筛选排除所有较小的值

function isBigEnough(element) {
  return element >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]

every()

every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。

注意:若收到一个空数组,此方法在一切情况下都会返回 true。

const isBelowThreshold = (currentValue) => currentValue < 40;

const array1 = [1, 30, 39, 29, 10, 13];

array1.every(isBelowThreshold) //true

every 方法为数组中的每个元素执行一次 callback 函数,直到它找到一个会使 callback 返回 falsy 的元素。如果发现了一个这样的元素,every 方法将会立即返回 false。否则,callback 为每一个元素返回 trueevery 就会返回 true

检测所有数组元素的大小

下例检测数组中的所有元素是否都大于 10。

function isBigEnough(element, index, array) {
  return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough);   // false
[12, 54, 18, 130, 44].every(isBigEnough); // true

使用箭头函数

箭头函数为上面的检测过程提供了更简短的语法。

[12, 5, 8, 130, 44].every(x => x >= 10); // false
[12, 54, 18, 130, 44].every(x => x >= 10); // true

some()

some() 方法测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。

注意:如果用一个空数组进行测试,在任何情况下它返回的都是false

some() 为数组中的每一个元素执行一次 callback 函数,直到找到一个使得 callback 返回一个“真值”(即可转换为布尔值 true 的值)。如果找到了这样一个值,some() 将会立即返回 true。否则,some() 返回 false

测试数组元素的值

下面的例子检测在数组中是否有元素大于 10。

function isBiggerThan10(element, index, array) {
  return element > 10;
}

[2, 5, 8, 1, 4].some(isBiggerThan10);  // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true

使用箭头函数测试数组元素的值

箭头函数 可以通过更简洁的语法实现相同的用例.

[2, 5, 8, 1, 4].some(x => x > 10);  // false
[12, 5, 8, 1, 4].some(x => x > 10); // true

reduce() 数组归并

参考这篇文章:取数组的最大值(ES5、ES6),详解Math.max() 和 reduce() API

flat() 数组扁平化

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

语法

var newArray = arr.flat(depth)

depth 可选 指定要提取嵌套数组的结构深度,默认值为 1。

返回一个包含将数组与子数组中所有元素的新数组。

扁平化嵌套数组

var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

扁平化与移除数组空项

flat() 方法会移除数组中的空项:

var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]

查看全部文章

博文系列目录

  • JavaScript 深入系列
  • JavaScript 专题系列
  • JavaScript 基础系列
  • 网络系列
  • 浏览器系列
  • Webpack 系列
  • Vue 系列
  • 性能优化与网络安全系列
  • HTML 应知应会系列
  • CSS 应知应会系列

交流

各系列文章汇总:https://github.com/yuanyuanbyte/Blog

我是圆圆,一名深耕于前端开发的攻城狮。

weixin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant