js中关于数组的一些细节知识

push

作用:向数组"末尾"追加新的内容

参数:追加的内容(可以是一个,也可是多个)

返回值:新增后数组的长度

原有数组改变

JavaScript

ini 复制代码
var arr = [
  { name: 'lee', age: 36 },
  { name: 'wang', age: 31 }
];
arr.push({ name: 'song', age: 30 });
console.log(arr);
11.png

pop

作用:删除数组最后一项

参数:无

返回:被删除的那一项内容

原有数组改变

JavaScript

ini 复制代码
var arr = [
  { name: 'lee', age: 36 },
  { name: 'wang', age: 31 },
  { name: 'gao', age: 50 }
];
arr.pop();
console.log(arr);
11.png

shift

作用:删除数组中的第一项

参数:无

返回:被删除的那一项内容

原有数组改变

JavaScript

ini 复制代码
var arr = [
  { name: 'lee', age: 36 },
  { name: 'wang', age: 31 },
  { name: 'gao', age: 50 }
];
arr.shift();
console.log(arr);
11.png

unshift

作用:向数组开始位置追加新内容

参数:要新增的内容

返回:新增后数组的长度

原有数组改变

JavaScript

ini 复制代码
var arr = [
  { name: 'lee', age: 36 },
  { name: 'wang', age: 31 },
  { name: 'gao', age: 50 }
];
arr.unshift({ name: 'xu', age: 33 }, {});
console.log(arr);
11.png

【删除:ary.splice(n,m)】

从索引n(start)开始,删除m(deleteCount)个内容,把删除的部分以一个新数组返回,原有数组改变

JavaScript

ini 复制代码
var arr = [12, 23, 34, 45, 56, 67, 78, 89, 90];
var ns = arr.splice(2, 3);
console.log(arr, ns);

如果不指定m或者删除的个数大于长度,都是删除到数组的末尾

【新增:ary.splice(n,0,x,...)】

从索引n(start)开始删除零项(没删除),把X(items)或者更多需要插入的内容存放到数组中索引N的"前面"

JavaScript

ini 复制代码
var arr = [12, 23, 34, 45, 56, 67, 78, 89, 90];
arr.splice(4, 0, 100, 200, { name: 'qian', age: 45 });
console.log(arr);
11.png

【修改:ary.splice(n,m,x,...)】

修改的原理就是把原有内容删除掉,然后用新的内容替换这部分信息即可

JavaScript

ini 复制代码
var arr = [12, 23, 34, 45, 56, 67, 78, 89, 90];
var re = arr.splice(2, 1, 100, 200, { name: 'qian', age: 45 });
console.log(arr, re);

JavaScript

scss 复制代码
//=>删除最后一项
ary.pop();
ary.splice(ary.length - 1);
ary.length--

JavaScript

ini 复制代码
//=>向数组末尾追加新内容
ary.push(100);
ary.splice(ary.length, 0, 100);
ary[ary.length] = 1;

不建议基于delete删除数组中的某一项,虽然内容没有了,但是数组的length长度没有改变。

slice

作用:在一个数组中,按照条件查找出其中的部分内容

参数:两个参数(n/m),从索引n开始,找到索引m处,但是不包含m

返回:以一个新数组存储查找的内容

原有数组不会变

JavaScript

ini 复制代码
var arr = [12, 23, 34, 45, 56, 67, 78, 89, 90];
var newArr1 = arr.slice(2, 7);
var newArr2 = arr.slice(2);
11.png

JavaScript

ini 复制代码
var newArr3 = arr.slice(0);
var newArr4 = arr.slice();
var newArr5 = arr.slice(-3, -1);
console.log(arr);
console.log(newArr1);
console.log(newArr2);
console.log(newArr3, newArr3 === arr);
console.log(newArr4, newArr4 === arr);
console.log(newArr5);

实现数组的克隆:克隆的一个新数组,和原有数组内容一样,但不是相同的堆内存空间,两个数组不相等、独立的。

concat

作用:实现多个数组(或者值)的拼接

参数:数组或者值

返回:拼接后的新数组

原有数组不变

JavaScript

ini 复制代码
var ary1 = [12, 23];
var ary2 = [100, 200];
var ary3 = [1000, 2000];
var newArr = ary1.concat(ary2, '珠峰', ary2, ary3);
console.log(newArr);
11.png

toString

作用:把数组转换为字符串参数:无

返回:数组中的每一项用逗号分隔的字符串

原有数组不变

JavaScript

ini 复制代码
var ary1 = [12, 23, { name: 'lee', age: 29 }];
var str = ary1.toString();
console.log(str);
11.png

join

作用:和toString类似,也是把数组转换为字符串,但是我们可以设置变为字符串后,每一项之间的连接符参数:指定的链接符

返回:字符串

原有数组不变

JavaScript

ini 复制代码
var ary1 = [12, 23, 34, 45, { name: 'lee', age: 29 }];
var str1 = ary1.join(',');
var str2 = ary1.join('+');
console.log(str1);
console.log(str2);
var num = eval([1, 2, 3, 45, 6, 7].join('+'));
console.log(num);

reverse

作用:把数组倒过来排列

参数:无

返回:排列后的新数组

原有数组改变

JavaScript

ini 复制代码
var ary = [12, 23, 34, 45, { name: 'lee', age: 29 }];
ary.reverse();
console.log(ary);
11.png

sort

作用:给数组排序

参数:无/函数

返回:排序后的新数组

原有数组改变

JavaScript

css 复制代码
var ary = [1, 3, 8, 3, 5, 7, 34, 89, 21];
ary.sort(function(a, b) {
  return a - b; //升序
  // return b-a; //降序
})
console.log(ary);

indexOf / lastIndexOf

这两个方法不兼容IE低版本浏览器(IE6~8)

作用:检测当前值在数组中第一次或者最后一次出现位置的索引

参数:要检测的值

返回:索引

原有数组不变

基于indexOf检测,如果数组中有这一项,返回一个大于等于零的索引,如果没有,返回的索引值为-1

JavaScript

ini 复制代码
var obj = { name: 'lee', age: 29 };
var ary = [1, 3, 8, 3, 5, 7, obj, 34, 89, 21];
if (ary.indexOf(89) > -1) {
  //ary包含100这项
  console.log(`包含89`);
}
if (ary.indexOf(obj)) {
  console.log(`包含${obj}这项`);
}
11.png

every

every()方法,针对数组中的每一个元素进行比对,只要有一个元素比对结果为false则返回false,反之要所有的元素比对结果为true才为true.

JavaScript

ini 复制代码
var a = [1, 2, 3, 4, 5, 6];
var b = a.every(function(x) {
  return x < 8;
})
var c = a.every(function(x) {
  return x < 6;
})
console.log(b, c);

some

some()方法,同样是针对数组中的每一个元素,但是这个方法是,只要有一个元素比对结果为true,返回结果就为true,反之要所有的元素比对结果为false才为false

JavaScript

ini 复制代码
var a = [1, 2, 3, 4, 5, 6];
var b = a.some(function(x) {
  return x > 10;
})
var c = a.some(function(x) {
  return x < 5;
})
console.log(b, c);




filter

scss 复制代码
filter()方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素; 不会改变原始数组

JavaScript

ini 复制代码
let oldArr = [
  { name: 'tom', age: 13 },
  { name: 'tom2', ge: 14 },
  { name: 'tom3', age: 15 },
  { name: 'tom4', age: 16 },
];
let newArr = oldArr.filter((item, index, arr) => {
  return item.age >= 15
});
console.log(oldArr);
console.log(newArr);

函数返回布尔值

11.png

find

find() 返回数组中第一个满足条件的数据

JavaScript

javascript 复制代码
var num = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var newNum1 = num.find((item, index) => {
  return item > 40;
})
console.log("newNum1 = " + newNum1); //50

findIndex

findIndex() 返回数组中第一个满足条件的索引(从0开始), 不满足返回-1

JavaScript

javascript 复制代码
var num = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var newNum2 = num.findIndex((item, index) => {
  return item > 40;
})
console.log("newNum2 = " + newNum2); //4

**

**

includes

includes() 判断数组宏是否包含某值,返回 true 或 false

语法:arr.includes(searchElement[, fromIndex])

JavaScript

ini 复制代码
var num = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var newNum7 = num.includes(40);
var newNum8 = num.includes(40, 5); //从索引5的位置开始向后查找
console.log("newNum7 = " + newNum7); //true
console.log("newNum8 = " + newNum8); //false

JavaScript

less 复制代码
const arr = ['es6', 'es7', 'es8', 'es9']

console.log(arr.includes('es7'))  // true
console.log(arr.includes('es7', 2)) // false ->从数组的第二个下标开始查找
console.log(arr.includes('es8', -1)) // false ->从数组的倒数第一个下标开始往后查找
console.log(arr.includes('es8', -2)) // true  ->从数组的倒数第二个下标开始往后查找

const _arr = ['es6', ['es7', 'es8'], 'es9']
console.log(_arr.includes(['es7', 'es8']))  // false
console.log(_arr.indexOf( ['es7', 'es8']))  // -1
//includes、indexOf 都只能查找基本数据类型,不能查找复合数据类型

const __arr= ['es6', ['es7', 'es8'], NaN, 'es9', 2]
console.log(__arr.includes(NaN))  // true
console.log(__arr.indexOf( NaN))  // -1

console.log(__arr.includes(2))    // true
console.log(__arr.includes('2'))  // false

console.log(__arr.indexOf(2))   // 4 
console.log(__arr.indexOf('2')) // -1

****

foreach / map

foreach 和 map 都是数组的迭代方法,对数组的每一项执行给定函数,不会改变原数组。两者的区别就在于 foreach 没有返回值,而 map 会返回每项执行完毕后数据组成的新数组。

所以在选择迭代方法时,如果不需要返回新数组,就选择 foreach , 如果需要得到的新数组,就选择 map 。

Foreach

语法: array.forEach(function(currentValue, index, arr), thisValue)

forEach()方法用于调用数组的每一个元素,并将元素传递给回调函数

11.png

JavaScript

javascript 复制代码
let colors = ['red', 'blue', 'green'];
colors.forEach((item, $index, arr) => {
    console.log(`${item} => ${$index} => ${arr}`);
})

forEach采用抛出一个异常来终止循环 **

**

JavaScript

javascript 复制代码
const arr = [1, 2, 3, 4, 5];
try {
  arr.forEach(item => {
    if (item === 3) {
      throw ('终止循环'); // 抛出一个异常
    }
    console.log('val=' + item); // 1,2
  });
} catch (e) {
  console.log('catch内容:' + e); // catch内容:终止循环
}

使用 return 方式(不能终止)

跳过值为3时,再继续循环

JavaScript

javascript 复制代码
/* 1.使用 return */
arr.forEach(item => {
  if (item === 3) {
    return; // 跳过itme为3
  }
  console.log('val=' + item); // 1,2,4,5
});

使用 break 方式(报错)

报错 Uncaught SyntaxError: Illegal break statement

JavaScript

ini 复制代码
/* 2.使用 break */
arr.forEach(item => {
  if (item === 3) {
    break; // 报错 Uncaught SyntaxError: Illegal break statement
  }
  console.log('val=' + item);
});

使用 continue 方式(报错)

报错 Uncaught SyntaxError: Illegal continue statement: no surrounding iteration statement

JavaScript

ini 复制代码
/* 3.使用 continue */
arr.forEach(item => {
  if (item === 3) {
    continue; // 报错 Uncaught SyntaxError: Illegal continue statement: no surrounding iteration statement
  }
  console.log('val=' + item);
});

map

语法:array.map(function(currentValue,index,arr), thisValue)

map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

map() 方法按照原始数组元素顺序依次处理元素。

注意: map() 不会对空数组进行检测。

注意: map() 不会改变原始数组。

JavaScript

javascript 复制代码
var arr = [
  { name: "zs", age: 12 },
  { name: "ls", age: 13 },
  { name: "ww", age: 16 },
  { name: "whh", age: 20 },
];
var item = arr.map((ele, index) => {
  return {
    name: ele.name + "__技术部员工",
    age: ele.age + 10
  }
})
console.log(item);
11.png

keys

keys() 方法用于从数组创建一个包含数组键的可迭代对象。

如果对象是数组返回 true,否则返回 false。

c 复制代码
语法:array.keys()

JavaScript

ini 复制代码
var arr = [
  { name: "zs", age: 12 },
  { name: "ls", age: 13 },
  { name: "ww", age: 16 },
  { name: "whh", age: 20 },
];
var iterator = arr.keys();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
11.png

reduce

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。

reduce() 可以作为一个高阶函数,用于函数的 compose。

注意: reduce() 对于空数组是不会执行回调函数的。

javascript 复制代码
语法:array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
11.png

arr 表示将要原数组;

prev 表示上一次调用回调时的返回值,或者初始值 init;

cur 表示当前正在处理的数组元素;

index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;

init 表示初始值。

常用的参数只有两个:prev 和 cur。

数组求和、求乘积

JavaScript

javascript 复制代码
var arr = [1, 2, 3, 4];
var sum = arr.reduce((x, y) => x + y)
var mul = arr.reduce((x, y) => x * y)
console.log(sum); //求和,10
console.log(mul); //求乘积,24

JavaScript

javascript 复制代码
//函数参数求和
function foo(x, y, z) {
  let sum = 0;
  // Array.prototype.forEach.call(arguments, function(item) {
  //   sum += item
  // })
  Array.from(arguments).forEach(item => {
    sum += item
  })
  return sum
}
console.log(foo(1,2,3)) // 6

JavaScript

javascript 复制代码
function foo(...args) {
  console.log(args) // [ 1, 2, 3 ]
  let sum = 0
  args.forEach(item => {
    sum += item
  })
  return sum
}

let sum = foo(1,2,3)
console.log(sum)  // 6

**

**

**

**

计算数组中每个元素出现的次数

JavaScript

ini 复制代码
let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
let nameNum = names.reduce((pre, cur) => {
  if (cur in pre) {
    pre[cur]++
  } else {
    pre[cur] = 1
  }
  return pre
}, {})
console.log(nameNum); //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}

数组去重

JavaScript

javascript 复制代码
let arr = [1, 2, 3, 4, 4, 1]
let newArr = arr.reduce((pre, cur) => {
  if (!pre.includes(cur)) {
    return pre.concat(cur)
  } else {
    return pre
  }
}, [])
console.log(newArr); // [1, 2, 3, 4]

JavaScript

javascript 复制代码
let arr = [1,2,3,4,8,2,4,5]
let s = Array.from(new Set(arr))
console.log(s)

JavaScript

javascript 复制代码
let arr1 = [1,2,3,4]
let arr2 = [3,5,6,8,2]
let s = Array.from(new Set([...arr1, ...arr2]))
console.log(s)  //[1, 2, 3, 4, 5, 6, 8]

JavaScript

ini 复制代码
let arr1 = [1,2,3,4,'world']
let arr2 = [3,5,'hello',6,8,2]
let arrAll=[...new Set(arr1.concat(arr2))]
console.log(arrAll) //[1, 2, 3, 4, 'world', 5, 'hello', 6, 8]

对象里属性求和

JavaScript

ini 复制代码
var result = [
  { subject: 'math', score: 10 },
  { subject: 'chinese', score: 20 },
  { subject: 'english', score: 30 }
];
var sum = result.reduce(function(prev, cur) {
  return cur.score + prev;
}, 0);
console.log(sum) //60

****js数组对象,按数组元素相同属性值分组

JavaScript

ini 复制代码
const arr = [
  { id: 1, type: 'A', name: 'John' },
  { id: 2, type: 'B', name: 'Mike' },
  { id: 3, type: 'A', name: 'Sam' },
  { id: 4, type: 'C', name: 'David' },
  { id: 5, type: 'B', name: 'Adam' },
  { id: 6, type: 'A', name: 'Tom' },
];

const grouped = arr.reduce((acc, cur) => {
  const key = cur.type;
  if (!acc[key]) {
    acc[key] = [];
  }
  acc[key].push(cur);
  return acc;
}, {});

console.log(grouped);

输出:

JavaScript

bash 复制代码
{
  A: [
    { id: 1, type: 'A', name: 'John' },
    { id: 3, type: 'A', name: 'Sam' },
    { id: 6, type: 'A', name: 'Tom' }
  ],
  B: [
    { id: 2, type: 'B', name: 'Mike' },
    { id: 5, type: 'B', name: 'Adam' }
  ],
  C: [
    { id: 4, type: 'C', name: 'David' }
  ]
}

这里使用 reduce() 方法,初始值为一个空对象 {},然后对于每个元素进行处理,将其归为对应类型的数组中,最终得到一个以类型为键,以对应类型的元素数组为值的对象。

【Array.isArray()、Array.from()】

**Array.from()方法

**

Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组。

那么什么是类数组对象呢?所谓类数组对象,最基本的要求就是具有length属性的对象。

Array.from有三个参数,Array.from(arrayLike[, mapFn[, thisArg]]),

arrayLike: 想要转换成数组的伪数组对象或可迭代对象;

mapFn: 如果指定了该参数,新数组中的每个元素会执行该回调函数;

thisArg: 可选参数,执行回调函数 mapFn 时 this 对象。该方法的返回值是一个新的数组实例(真正的数组)。

将类数组对象转换为真正数组:

JavaScript

bash 复制代码
let arrayLike = {
    0: 'tom', 
    1: '65',
    2: '男',
    3: ['jane','john','Mary'],
    'length': 4
}
let arr = Array.from(arrayLike)
console.log(arr) // ['tom','65','男',['jane','john','Mary']]

那么,如果将上面代码中length属性去掉呢?实践证明,答案会是一个长度为0的空数组。

这里将代码再改一下,就是具有length属性,但是对象的属性名不再是数字类型的,而是其他字符串型的,代码如下:

JavaScript

javascript 复制代码
let arrayLike = {
    'name': 'tom', 
    'age': '65',
    'sex': '男',
    'friends': ['jane','john','Mary'],
    length: 4
}
let arr = Array.from(arrayLike)
console.log(arr)  // [ undefined, undefined, undefined, undefined ]

会发现结果是长度为4,元素均为undefined的数组

由此可见,要将一个类数组对象转换为一个真正的数组,必须具备以下条件:

1、该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组。

2、该类数组对象的属性名必须为数值型或字符串型的数字

ps: 该类数组对象的属性名可以加引号,也可以不加引号

将Set结构的数据转换为真正的数组:

JavaScript

csharp 复制代码
let arr = [12,45,97,9797,564,134,45642]
let set = new Set(arr)
console.log(Array.from(set))  // [ 12, 45, 97, 9797, 564, 134, 45642 ]

Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。如下

JavaScript

javascript 复制代码
let arr = [12,45,97,9797,564,134,45642]
let set = new Set(arr)
console.log(Array.from(set, item => item + 1)) // [ 13, 46, 98, 9798, 565, 135, 45643 ]

将字符串转换为数组:

JavaScript

python 复制代码
let  str = 'hello world!';
console.log(Array.from(str)) // ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d", "!"]

Array.from参数是一个真正的数组:

JavaScript

javascript 复制代码
console.log(Array.from([12,45,47,56,213,4654,154]))

像这种情况,Array.from会返回一个一模一样的新数组

在ES6中,扩展运算符(...)也可以将某些数据结构转为数组。只不过它需要在背后调用遍历器接口Symbol.iterator。值得注意的是如果一个对象没有部署遍历器接口,使用扩展运算符是无法将类似数组对象转换成数组。

JavaScript

matlab 复制代码
function doSomething (){ 
  return [...arguments] 
}
doSomething('a','b','c'); // ["a","b","c"]

只要是部署了iterator接口的数据结构,Array.from都能将其转为数组:

在ES6中,扩展运算符(...)也可以将某些数据结构转为数组。只不过它需要在背后调用遍历器接口Symbol.iterator。值得注意的是如果一个对象没有部署遍历器接口,使用扩展运算符是无法将类似数组对象转换成数组。

在ES6中,扩展运算符(...)也可以将某些数据结构转为数组。只不过它需要在背后调用遍历器接口Symbol.iterator。值得注意的是如果一个对象没有部署遍历器接口,使用扩展运算符是无法将类似数组对象转换成数组。

只要是部署了iterator接口的数据结构,Array.from都能将其转为数组:

Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,处理后的值放入返回的数组。

JavaScript

javascript 复制代码
Array.from([1, 2, 3], (x) => x * x)// [1, 4, 9]
// 等同于
Array.from([1,2,3].map(x => x * x))

如果map函数里面用到了this关键字,还可以传入Array.from的第三个参数,用来绑定this。

Array.from()可以将各种值转为真正的数组,并且还提供map功能。这实际上意味着,只要有一个原始的数据结构,你就可以先对它的值进行处理,然后转成规范的数组结构,进而就可以使用数量众多的数组方法。

JavaScript

css 复制代码
Array.from({ length: 2 }, () => 'jack')// ['jack', 'jack']

Array.isArray() 判断是不是数组

JavaScript

javascript 复制代码
// 下面的函数调用都返回 true
console.log(Array.isArray([]));
console.log(Array.isArray([1]));
console.log(Array.isArray(new Array()));
// 下面的函数调用都返回 false
console.log(Array.isArray());
console.log(Array.isArray({}));
console.log(Array.isArray(null));
console.log(Array.isArray(undefined));
console.log(Array.isArray(17));
console.log(Array.isArray('Array'));
console.log(Array.isArray(true));
console.log(Array.isArray(false));

JavaScript

javascript 复制代码
var lis = document.querySelector('li');
console.log(Array.isArray(lis)); //false
var lis2 = Array.from(lis);
console.log(Array.isArray(lis2)); //true

【Array.of()】将一系列值转换成数组

当调用 new Array( )构造器时,根据传入参数的类型与数量的不同,实际上会导致一些不同的结果, 例如:

JavaScript

ini 复制代码
let items = new Array(2) ;
console.log(items.length) ; // 2
console.log(items[0]) ; // undefined
console.log(items[1]) ;

JavaScript

javascript 复制代码
let items = new Array(1, 2) ;
console.log(items.length) ; // 2
console.log(items[0]) ; // 1
console.log(items[1]) ; // 2

当使用单个数值参数来调用 Array 构造器时,数组的长度属性会被设置为该参数。 如果使用多个参数(无论是否为数值类型)来调用,这些参数也会成为目标数组的项。数组的这种行为既混乱又有风险,因为有时可能不会留意所传参数的类型。

ES6 引入了Array.of( )方法来解决这个问题。该方法的作用非常类似Array构造器,但在使用单个数值参数的时候并不会导致特殊结果。Array.of( )方法总会创建一个包含所有传入参数的数组,而不管参数的数量与类型:

JavaScript

ini 复制代码
let items = Array.of(1, 2);
console.log(items.length); // 2
console.log(items[0]); // 1
console.log(items[1]); // 2
items = Array.of(2);
console.log(items.length); // 1
console.log(items[0]); // 2

Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载,而且他们的行为非常统一。

JavaScript

ini 复制代码
const arr = Array.of(1);
console.log(arr); //[1]

copyWithin()

copyWithin() 方法用于从数组的指定位置拷贝元素到数组的另一个指定位置中。

返回修改后的数组(即直接修改原数组),不会改变数组的长度

Bash

sql 复制代码
array.copyWithin(target, start, end)

target为必需,复制到指定位置目标索引,可以为负值,为负值后,索引为length+target

start 可选,元素复制的起始位置,省略,默认为0。可以为负值,为负值后,索引为length+start

end 可选,元素复制的结束位置(不包含),默认为数组的length,可以为负值,为负值后,索引为length+end

若start的值大于end,则直接返回原数组,不进行任何处理

JavaScript

css 复制代码
var arr = ["apple","banana","cover","double"]
arr.copyWithin(1,2,3)
console.log(arr)
// Array [ "apple", "cover", "cover", "double" ]

start和end是先进行比较大小,然后在进行负值处理,

JavaScript

css 复制代码
var arr =  [ "apple", "banana", "cover", "double" ]
arr.copyWithin(0,-3,-1)
console.log(arr)
// Array [ "banana", "cover", "cover", "double" ]

flat()

数组的成员有时还是数组,Array.prototype.flat()用于将嵌套的数组"拉平",变成一维数组。该方法返回一个新数组,对原数据没有影响。

JavaScript

ini 复制代码
let arr = [1, 2, [3, 4]]
let newArr = arr.flat()
console.log(newArr) //[1, 2, 3, 4]

上面代码中,原数组的成员里面有一个数组,flat()方法将子数组的成员取出来,添加在原来的位置。

flat()默认只会"拉平"一层,如果想要"拉平"多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。

JavaScript

ini 复制代码
let arr = [1, 2, [3, 4]]
let newArr = arr.flat()
console.log(newArr) // [1, 2, 3, 4]

arr = [1, 2, [3, [4, 5]]]
newArr = arr.flat(2)
console.log(newArr) // [1, 2, 3, 4, 5]

上面代码中,flat()的参数为2,表示要拉平两层的嵌套数组。

如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。

JavaScript

ini 复制代码
let arr = [1, 2, [3, [4, 5]]]
let newArr = arr.flat(Infinity)
console.log(newArr) // [1, 2, 3, 4, 5]

如果原数组有空位,flat()方法会跳过空位。

JavaScript

ini 复制代码
arr = [1, 2, , 4, 5]
newArr = arr.flat(Infinity)
console.log(newArr) // [1, 2, 4, 5]

flatMap()方法对原数组的每个成员执行一个函数,相当于执行Array.prototype.map(),然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组。

JavaScript

ini 复制代码
let arr = [1, 2, 3, 4, 5]
let newArr=arr.flatMap(x => {
  return [x, x*2]
})
console.log(newArr) // [1, 2, 2, 4, 3, 6, 4, 8, 5, 10]

entries()

entries() 方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。

语法

scss 复制代码
arr.entries()

返回值

一个新的 Array 迭代器对象。Array Iterator是对象,它的原型(proto :Array Iterator)上有一个next方法,可用用于遍历迭代器取得原数组的 [key,value]。

1、 Array Iterator

JavaScript

ini 复制代码
var arr = ["a", "b", "c"];
var iterator = arr.entries();
console.log(iterator);

2、iterator.next()

JavaScript

ini 复制代码
var arr = ["a", "b", "c"];
var iterator = arr.entries();
console.log(iterator.next());

Bash

vbnet 复制代码
// iterator.next() 返回一个对象,对于有元素的数组,
// 是 next{ value: Array(2), done: false };
// next.done 用于指示迭代器是否完成:在每次迭代时进行更新而且都是 false,
// 直到迭代器结束 done 才是 true。
// next.value 是一个 ["key","value"] 的数组,是返回的迭代器中的元素值。

3、iterator.next 方法运行

JavaScript

ini 复制代码
var arr = ["a", "b", "c"];
var iter = arr.entries();
var a = [];

// for(var i=0; i< arr.length; i++){   // 实际使用的是这个
for(var i=0; i< arr.length+1; i++){    // 注意,是 length+1,比数组的长度大
    var tem = iter.next();             // 每次迭代时更新 next
    console.log(tem.done);             // 这里可以看到更新后的 done 都是 false
    if(tem.done !== true){             // 遍历迭代器结束 done 才是 true
        console.log(tem.value);
        a[i]=tem.value;
    }
}

console.log(a);                         // 遍历完毕,输出 next.value 的数组

4、二维数组按行排序

JavaScript

ini 复制代码
function sortArr(arr) {
  debugger
  var goNext = true;
  var entries = arr.entries();
  while (goNext) {
      var result = entries.next();
      if (result.done !== true) {
          result.value[1].sort((a, b) => a - b);
          goNext = true;
      } else {
          goNext = false;
      }
  }
  return arr;
}

var arr = [[1,34],[456,2,3,44,234],[4567,1,4,5,6],[34,78,23,1]];
sortArr(arr);
console.log(arr)

5、使用for...of 循环 -for-of / for-in

无论是for...in还是for...of语句都是迭代一些东西。它们之间的主要区别在于它们的迭代方式。

for...in 语句以任意顺序迭代对象的可枚举属性

for...of 语句遍历可迭代对象定义要迭代的数据。

javascript 复制代码
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];
iterable.foo = 'hello';

for (let i in iterable) {
  console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs 0, 1, 2, "foo"
  }
}

for (let i of iterable) {
  console.log(i); // logs 3, 5, 7
}

for...in 会迭代原型链上的所有可枚举属性,如需迭代当前对象的可枚举属性,可以使用 obj.hasOwnProperty(key)进行拦截,并且它不记录值,只记录键。

1 遍历数组通常用for循环

ES5的话也可以使用forEach,ES5具有遍历数组功能的还有map、filter、some、every、reduce、reduceRight等,只不过他们的返回结果不一样。但是使用foreach遍历数组的话,使用break不能中断循环,使用return也不能返回到外层函数。

JavaScript

ini 复制代码
Array.prototype.method=function(){
  console.log(this.length);
}
var myArray=[1,2,4,5,6,7]
myArray.name="数组"
for (var index in myArray) {
  console.log(myArray[index]);
}

2 for in遍历数组的毛病

1.index索引为字符串型数字,不能直接进行几何运算

2.遍历顺序有可能不是按照实际数组的内部顺序

3.使用for in会遍历数组所有的可枚举属性,包括原型。例如上栗的原型方法method和name属性

所以for in更适合遍历对象,不要使用for in遍历数组。

那么除了使用for循环,如何更简单的正确的遍历数组达到我们的期望呢(即不遍历method和name),ES6中的for of更胜一筹.

JavaScript

ini 复制代码
Array.prototype.method=function(){
  console.log(this.length);
}
var myArray=[1,2,4,5,6,7]
myArray.name="数组";
for (var value of myArray) {
  console.log(value);
}

记住,for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值。

for of遍历的只是数组内的元素,而不包括数组的原型属性method和索引name

3 遍历对象

遍历对象 通常用for in来遍历对象的键名

JavaScript

javascript 复制代码
Object.prototype.method=function(){
  console.log(this);
}
var myObject={
  a:1,
  b:2,
  c:3
}
for (var key in myObject) {
  console.log(key);
}

for in 可以遍历到myObject的原型方法method,如果不想遍历原型方法和属性的话,可以在循环内部判断一下,hasOwnPropery方法可以判断某属性是否是该对象的实例属性

JavaScript

scss 复制代码
for (var key in myObject) {
  if(myObject.hasOwnProperty(key)){
    console.log(key);
  }
}

同样可以通过ES5的Object.keys(myObject)获取对象的实例属性组成的数组,不包括原型方法和属性

JavaScript

javascript 复制代码
Object.prototype.method=function(){
  console.log(this);
}
var myObject={
  a:1,
  b:2,
  c:3
}

总结

  1. for..of适用遍历数/数组对象/字符串/map/set等拥有迭代器对象的集合.但是不能遍历对象,因为没有迭代器对象.与forEach()不同的是,它可以正确响应break、continue和return语句

  2. for-of循环不支持普通对象,但如果你想迭代一个对象的属性,你可以用for-in循环(这也是它的本职工作)或内建的Object.keys()方法:

JavaScript

vbnet 复制代码
for (var key of Object.keys(someObject)) {
  console.log(key + ": " + someObject[key]);
}
  1. 遍历map对象时适合用解构,例如;

JavaScript

javascript 复制代码
for (var [key, value] of phoneBookMap) {
  console.log(key + "'s phone number is: " + value);
}
  1. 当你为对象添加myObject.toString()方法后,就可以将对象转化为字符串,同样地,当你向任意对象添加myObjectSymbol.iterator方法,就可以遍历这个对象了。
    举个例子,假设你正在使用jQuery,尽管你非常钟情于里面的.each()方法,但你还是想让jQuery对象也支持for-of循环,你可以这样做:

JavaScript

javascript 复制代码
jQuery.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

所有拥有Symbol.iterator的对象被称为可迭代的。在接下来的文章中你会发现,可迭代对象的概念几乎贯穿于整门语言之中,不仅是for-of循环,还有Map和Set构造函数、解构赋值,以及新的展开操作符。

  1. for...of的步骤
    for-of循环首先调用集合的Symbol.iterator方法,紧接着返回一个新的迭代器对象。迭代器对象可以是任意具有.next()方法的对象;for-of循环将重复调用这个方法,每次循环调用一次。举个例子,这段代码是我能想出来的最简单的迭代器:

JavaScript

javascript 复制代码
var zeroesForeverIterator = {
  [Symbol.iterator]: function () {
    return this;
  },
  next: function () {
    return {done: false, value: 0};
  }
};

JS数组遍历:

1.普通for循环

JavaScript

ini 复制代码
var arr = [1,2,0,3,9];
for ( var i = 0; i <arr.length; i++){
  console.log(arr[i]);
}

2.优化版for循环

使用变量,将长度缓存起来,避免重复获取长度,数组很大时优化效果明显

JavaScript

ini 复制代码
for(var j = 0,len = arr.length; j < len; j++){
  console.log(arr[j]);
}

3.forEach

ES5推出的,数组自带的循环,主要功能是遍历数组,实际性能比for还弱

JavaScript

javascript 复制代码
arr.forEach(function(value,i){
  console.log('forEach遍历:'+i+'--'+value);
})

forEach这种方法也有一个小缺陷:你不能使用break语句中断循环,也不能使用return语句返回到外层函数。

4.map遍历

map即是 "映射"的意思 用法与 forEach 相似,同样不能使用break语句中断循环,也不能使用return语句返回到外层函数。

JavaScript

javascript 复制代码
arr.map(function(value,index){
  console.log('map遍历:'+index+'--'+value);
});

map遍历支持使用return语句,支持return返回值

JavaScript

kotlin 复制代码
var temp=arr.map(function(val,index){
  console.log(val);
  return val*val
})
console.log(temp);

forEach、map都是ECMA5新增数组的方法,所以ie9以下的浏览器还不支持

5.for-of遍历

ES6新增功能

JavaScript

scss 复制代码
for( let i of arr){
  console.log(i);
}

5.1 for-of这个方法避开了for-in循环的所有缺陷

5.2与forEach()不同的是,它可以正确响应break、continue和return语句

for-of循环不仅支持数组,还支持大多数类数组对象,例如DOM NodeList对象。for-of循环也支持字符串遍历

JS对象遍历:

1.for-in遍历

for-in是为遍历对象而设计的,不适用于遍历数组。(遍历数组的缺点:数组的下标index值是数字,for-in遍历的index值"0","1","2"等是字符串)

for-in循环存在缺陷:循环会遍历对象自身的和继承的可枚举属性(不含Symbol属性)

JavaScript

ini 复制代码
for (var index in arr){
  console.log(arr[index]);
  console.log(index);
}

2.使用Object.keys()遍历

返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性).

JavaScript

ini 复制代码
var obj = {'0':'a','1':'b','2':'c'};
Object.keys(obj).forEach(function(key){
  console.log(key,obj[key]);
});

3.使用Object.getOwnPropertyNames(obj)遍历

返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性).

JavaScript

ini 复制代码
var obj = {'0':'a','1':'b','2':'c'};
Object.getOwnPropertyNames(obj).forEach(function(key){
  console.log(key,obj[key]);
});

4.使用Reflect.ownKeys(obj)遍历

返回一个数组,包含对象自身的所有属性,不管属性名是Symbol或字符串,也不管是否可枚举.

JavaScript

ini 复制代码
var obj = {'0':'a','1':'b','2':'c'};
Reflect.ownKeys(obj).forEach(function(key){
  console.log(key,obj[key]);
相关推荐
八了个戒7 小时前
「数据可视化 D3系列」入门第三章:深入理解 Update-Enter-Exit 模式
开发语言·前端·javascript·数据可视化
胚芽鞘6818 小时前
vue + element-plus自定义表单验证(修改密码业务)
javascript·vue.js·elementui
小陈同学呦8 小时前
聊聊双列瀑布流
前端·javascript·面试
键指江湖9 小时前
React 在组件间共享状态
前端·javascript·react.js
烛阴9 小时前
零基础必看!Express 项目 .env 配置,开发、测试、生产环境轻松搞定!
javascript·后端·express
诸葛亮的芭蕉扇9 小时前
D3路网图技术文档
前端·javascript·vue.js·microsoft
徐小夕10 小时前
花了2个月时间研究了市面上的4款开源表格组件,崩溃了,决定自己写一款
前端·javascript·react.js
拉不动的猪10 小时前
UniApp金融理财产品项目简单介绍
前端·javascript·面试
苏卫苏卫苏卫10 小时前
【Vue】案例——To do list:
开发语言·前端·javascript·vue.js·笔记·list
聪明的墨菲特i11 小时前
React与Vue:哪个框架更适合入门?
开发语言·前端·javascript·vue.js·react.js