百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

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

toyiye 2024-06-21 12:05 10 浏览 0 评论

push

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

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

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

原有数组改变

JavaScript

var arr = [
  { name: 'lee', age: 36 },
  { name: 'wang', age: 31 }
];
arr.push({ name: 'song', age: 30 });
console.log(arr);


pop

作用:删除数组最后一项

参数:无

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

原有数组改变

JavaScript

var arr = [
  { name: 'lee', age: 36 },
  { name: 'wang', age: 31 },
  { name: 'gao', age: 50 }
];
arr.pop();
console.log(arr);


shift

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

参数:无

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

原有数组改变

JavaScript

var arr = [
  { name: 'lee', age: 36 },
  { name: 'wang', age: 31 },
  { name: 'gao', age: 50 }
];
arr.shift();
console.log(arr);

unshift

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

参数:要新增的内容

返回:新增后数组的长度

原有数组改变

JavaScript

var arr = [
  { name: 'lee', age: 36 },
  { name: 'wang', age: 31 },
  { name: 'gao', age: 50 }
];
arr.unshift({ name: 'xu', age: 33 }, {});
console.log(arr);

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

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

JavaScript

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

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


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

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

JavaScript

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

//=>删除最后一项
ary.pop();
ary.splice(ary.length - 1);
ary.length--

JavaScript

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

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

slice

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

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

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

原有数组不会变

JavaScript

var arr = [12, 23, 34, 45, 56, 67, 78, 89, 90];
var newArr1 = arr.slice(2, 7);
var newArr2 = arr.slice(2);


JavaScript

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

var ary1 = [12, 23];
var ary2 = [100, 200];
var ary3 = [1000, 2000];
var newArr = ary1.concat(ary2, '珠峰', ary2, ary3);
console.log(newArr);

toString

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

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

原有数组不变

JavaScript

var ary1 = [12, 23, { name: 'lee', age: 29 }];
var str = ary1.toString();
console.log(str);


join

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

返回:字符串

原有数组不变

JavaScript

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

var ary = [12, 23, 34, 45, { name: 'lee', age: 29 }];
ary.reverse();
console.log(ary);


sort

作用:给数组排序

参数:无/函数

返回:排序后的新数组

原有数组改变

JavaScript

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

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}这项`);
}


every

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

JavaScript

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

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

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

JavaScript

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);

函数返回布尔值


find

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

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

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

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

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()方法用于调用数组的每一个元素,并将元素传递给回调函数


JavaScript

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

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

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

/* 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

/* 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

/* 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

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);


keys

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

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

语法:array.keys()

JavaScript

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());


reduce

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

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

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

语法:array.reduce(function(total, currentValue, currentIndex, arr), initialValue)


arr 表示将要原数组;
prev 表示上一次调用回调时的返回值,或者初始值 init;
cur 表示当前正在处理的数组元素;
index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;
init 表示初始值。

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

数组求和、求乘积

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

//函数参数求和
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

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

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

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

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

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

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

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

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

{
  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

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

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

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

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

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

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

JavaScript

console.log(Array.from([12,45,47,56,213,4654,154]))

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

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

JavaScript

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

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

Array.from({ length: 2 }, () => 'jack')// ['jack', 'jack']

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

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

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

let items = new Array(2) ;
console.log(items.length) ; // 2
console.log(items[0]) ; // undefined
console.log(items[1]) ;

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

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

const arr = Array.of(1);
console.log(arr); //[1]

copyWithin()

copyWithin() 方法用于从数组的指定位置拷贝元素到数组的另一个指定位置中。
返回修改后的数组(即直接修改原数组),不会改变数组的长度

Bash

array.copyWithin(target, start, end)

target为必需,复制到指定位置目标索引,可以为负值,为负值后,索引为length+target
start 可选,元素复制的起始位置,省略,默认为0。可以为负值,为负值后,索引为length+start
end 可选,元素复制的结束位置(不包含),默认为数组的length,可以为负值,为负值后,索引为length+end


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

JavaScript

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

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

JavaScript

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

flat()

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

JavaScript

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

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

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

JavaScript

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

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

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

JavaScript

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

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

JavaScript

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对象,该对象包含数组中每个索引的键/值对。

语法

arr.entries()

返回值

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

1、 Array Iterator

JavaScript

var arr = ["a", "b", "c"];
var iterator = arr.entries();
console.log(iterator);


2、iterator.next()

JavaScript

var arr = ["a", "b", "c"];
var iterator = arr.entries();
console.log(iterator.next());


Bash

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

3、iterator.next 方法运行

JavaScript

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

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 语句遍历可迭代对象定义要迭代的数据。

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

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

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

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

for (var key in myObject) {
  if(myObject.hasOwnProperty(key)){
    console.log(key);
  }
}

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

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

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

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

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

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

JS数组遍历:

1.普通for循环

JavaScript

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

2.优化版for循环

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

JavaScript

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

3.forEach

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

JavaScript

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

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

4.map遍历

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

JavaScript

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

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

JavaScript

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

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

for (var index in arr){
  console.log(arr[index]);
  console.log(index);
}

2.使用Object.keys()遍历

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

JavaScript

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

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

var obj = {'0':'a','1':'b','2':'c'};
Reflect.ownKeys(obj).forEach(function(key){
  console.log(key,obj[key]);

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码