01.遍历操作

01.forEach方法

01.使用讲解

forEach方法中的function回调有三个参数:

  • 第一个参数是遍历的数组内容,
  • 第二个参数是对应的数组索引,
  • 第三个参数是数组本身

foreach 语法:

  1. /*
  2. * JS中还为我们提供了—个方法,用来遍历数组
  3. * forEach()
  4. * -这个方法只支持IE8以上的浏览器
  5. * forEach()方法需要一个函数作为参数
  6. -像这种函数,由我们创建但是不由我们调用的,我们称为回调函数(由浏览器调用)
  7. -数组中有几个元素函数就会执行几次
  8. -每次执行时,浏览器会将遍历到的元素以实参的形式传递进来 我们可以来定义形参,来读取这些内容
  9. -浏览器会在回调函数中传递三个参数;
  10. 第一个参数,就是当前正在遍历的元素
  11. 第二个参数,就是当前正在遍历的元素的索引
  12. 第三个参数,就是正在遍历的数组
  13. */
  14. 数组.forEach(function(value , index , obj){
  15. });

示例 常规用法

  1. var array = ['a', 'b', 'c'];
  2. array.forEach(function(element) {
  3. console.log(element);
  4. });
  5. //a b c

全面示例

  1. var arr = [1,2,3,4];
  2. var sum =0;
  3. arr.forEach(function(value,index,array){
  4. array[index] == value; //结果为true
  5. sum+=value;
  6. });
  7. console.log(sum); //结果为 10

02.leetcode典型例题 最小操作次数使数组元素相等

题目

  1. 给定一个长度为 n 非空 整数数组,每次操作将会使 n - 1 个元素增加 1。找出让数组所有元素相等的最小操作次数。
  2. 示例:
  3. 输入:
  4. [1,2,3]
  5. 输出:
  6. 3
  7. 解释:
  8. 只需要3次操作(注意每次操作会增加两个元素的值):
  9. [1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]

题解

  1. /**
  2. * @param {number[]} nums
  3. * @return {number}
  4. */
  5. var minMoves = function(nums) {
  6. let min = nums[0];
  7. let res = 0;
  8. for(let i =0;i<nums.length;i++) {
  9. min = Math.min(min,nums[i])
  10. }
  11. // for(let j=0;j<nums.length;j++) {
  12. // res+=nums[j]-min
  13. // }
  14. nums.forEach(values=>{
  15. res+=values-min
  16. })
  17. return res
  18. };

03.打断forEach

https://blog.csdn.net/handy_csdn/article/details/105170806

004.提高效率写法 - 图1

  1. 给你一个排序后的字符列表 letters ,列表中只包含小写英文字母。另给出一个目标字母 target,请你寻找在这一有序列表里比目标字母大的最小字母。
  2. 在比较时,字母是依序循环出现的。举个例子:
  3. 如果目标字母 target = 'z' 并且字符列表为 letters = ['a', 'b'],则答案返回 'a'
  4. 示例:
  5. 输入:
  6. letters = ["c", "f", "j"]
  7. target = "a"
  8. 输出: "c"
  9. 输入:
  10. letters = ["c", "f", "j"]
  11. target = "c"
  12. 输出: "f"
  13. 输入:
  14. letters = ["c", "f", "j"]
  15. target = "d"
  16. 输出: "f"
  17. 输入:
  18. letters = ["c", "f", "j"]
  19. target = "g"
  20. 输出: "j"
  21. 输入:
  22. letters = ["c", "f", "j"]
  23. target = "j"
  24. 输出: "c"
  25. 输入:
  26. letters = ["c", "f", "j"]
  27. target = "k"
  28. 输出: "c"
  1. /**
  2. * @param {character[]} letters
  3. * @param {character} target
  4. * @return {character}
  5. */
  6. var nextGreatestLetter = function(letters, target) {
  7. var res ='';
  8. try{
  9. letters.forEach(item=>{
  10. if(item>target){
  11. res = item
  12. throw new Error('找到数据')
  13. }
  14. })
  15. }catch{
  16. return res
  17. }
  18. res=letters[0]
  19. return res
  20. };

02.filter方法

01.使用详解

定义和用法

  • filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
  • 注意:** filter() 不会对空数组进行检测。
  • 注意: filter() 不会改变原始数组。
  • 004.提高效率写法 - 图2

利用 filter 遍历出所有偶数:

  1. let arr = [56, 15, 48, 3, 7];
  2. let newArr = arr.filter(function (value, index, array) {
  3. return value % 2 === 0;
  4. });
  5. console.log(newArr)
  6. // [56, 48]

利用 filter 进行数组去重:

  1. function unique(arr) {
  2. return arr.filter(function(item, index, arr) {
  3. //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
  4. return arr.indexOf(item, 0) === index;
  5. });
  6. }
  7. var arr = [1,1,'RUNOOB','RUNOOB',true,true,15];
  8. console.log(unique(arr))
  9. // [1, "RUNOOB", true, 15]

取数组交集

  1. // 02.交集
  2. let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
  3. let arr2 = [3, 4, 5, 6, 5, 4, 3];
  4. // 看来我需要学学数组的一些方法
  5. let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
  6. console.log(result);

02.典型例题

01.500. 键盘行

  1. 给你一个字符串数组 words ,只返回可以使用在 美式键盘 同一行的字母打印出来的单词。键盘如下图所示。
  2. 美式键盘 中:
  3. 第一行由字符 "qwertyuiop" 组成。
  4. 第二行由字符 "asdfghjkl" 组成。
  5. 第三行由字符 "zxcvbnm" 组成。
  6. 示例 1
  7. 输入:words = ["Hello","Alaska","Dad","Peace"]
  8. 输出:["Alaska","Dad"]
  9. 示例 2
  10. 输入:words = ["omk"]
  11. 输出:[]
  12. 示例 3
  13. 输入:words = ["adsdf","sfd"]
  14. 输出:["adsdf","sfd"]

02.题解

https://leetcode-cn.com/problems/keyboard-row/solution/jian-pan-xing-by-ouuz-2/

  1. 解题思路
  2. 直接利用正则求解就可以了
  3. 可以直接利用库函数不用每次都写循环
  4. 修饰符用i,不用gi,gi会全局匹配,导致结果会漏掉
  5. 基础知识:
  6. g: 全局匹配
  7. i: 忽略大小写
  8. gi: 以上组合
  9. ^ 匹配一个输入或一行的开头,/^a/匹配"an A",而不匹配"An a"
  10. $ 匹配一个输入或一行的结尾,/a$/匹配"An a",而不匹配"an A"
  11. * 匹配前面元字符0次或多次,/ba*/将匹配b,ba,baa,baaa
  12. + 匹配前面元字符1次或多次,/ba+/将匹配ba,baa,baaa
  13. ? 匹配前面元字符0次或1次,/ba?/将匹配b,ba
  14. (x) 匹配x保存x在名为$1...$9的变量中
  15. x|y 匹配xy
  16. {n} 精确匹配n
  17. {n,} 匹配n次以上
  18. {n,m} 匹配n-m
  19. [xyz] 字符集(character set),匹配这个集合中的任一一个字符(或元字符)
  20. [^xyz] 不匹配这个集合中的任何一个字符
  21. [\b] 匹配一个退格符
  22. \b 匹配一个单词的边界
  23. \B 匹配一个单词的非边界
  24. \cX 这儿,X是一个控制符,/\cM/匹配Ctrl-M
  25. \d 匹配一个字数字符,/\d/ = /[0-9]/
  26. \D 匹配一个非字数字符,/\D/ = /[^0-9]/
  27. \n 匹配一个换行符
  28. \r 匹配一个回车符
  29. \s 匹配一个空白字符,包括\n,\r,\f,\t,\v
  30. \S 匹配一个非空白字符,等于/[^\n\f\r\t\v]/
  31. \t 匹配一个制表符
  32. \v 匹配一个重直制表符
  33. \w 匹配一个可以组成单词的字符(alphanumeric,这是我的意译,含数字),包括下划线,如[\w]匹配"$5.98"中的5,等于[a-zA-Z0-9]
  34. \W 匹配一个不可以组成单词的字符,如[\W]匹配"$5.98"中的$,等于[^a-zA-Z0-9]。
  35. 代码
  36. /**
  37. * @param {string[]} words
  38. * @return {string[]}
  39. */
  40. var findWords = function (words) {
  41. return words.filter(x => /(^[qwertyuiop]+$)|(^[asdfghjkl]+$)|(^[zxcvbnm]+$)/i.test(x))
  42. };

03.reduce方法

01.使用详解

1、语法

  1. arr.reduce(callback,[initialValue])

reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。

```css callback (执行数组中每个值的函数,包含四个参数)

  1. 1previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
  2. 2currentValue (数组中当前被处理的元素)
  3. 3index (当前元素在数组中的索引)
  4. 4array (调用 reduce 的数组)

initialValue (作为第一次调用 callback 的第一个参数。)

  1. > > <a name="fd2860c6"></a>
  2. #### 2、实例解析 initialValue 参数
  3. > 先看第一个例子
  4. > ```jsx
  5. var arr = [1, 2, 3, 4];
  6. var sum = arr.reduce(function(prev, cur, index, arr) {
  7. console.log(prev, cur, index);
  8. return prev + cur;
  9. })
  10. console.log(arr, sum);

打印结果:
1 2 1
3 3 2
6 4 3
[1, 2, 3, 4] 10

这里可以看出,上面的例子index是从1开始的,第一次的prev的值是数组的第一个值。数组长度是4,但是reduce函数循环3次。

再看第二个例子:

  1. var arr = [1, 2, 3, 4];
  2. var sum = arr.reduce(function(prev, cur, index, arr) {
  3. console.log(prev, cur, index);
  4. return prev + cur;
  5. },0) //注意这里设置了初始值
  6. console.log(arr, sum);

打印结果:
0 1 0
1 2 1
3 3 2
6 4 3
[1, 2, 3, 4] 10

这个例子index是从0开始的,第一次的prev的值是我们设置的初始值0,数组长度是4,reduce函数循环4次。

结论:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。

注意:如果这个数组为空,运用reduce是什么情况?

  1. var arr = [];
  2. var sum = arr.reduce(function(prev, cur, index, arr) {
  3. console.log(prev, cur, index);
  4. return prev + cur;
  5. })
  6. //报错,"TypeError: Reduce of empty array with no initial value"

但是要是我们设置了初始值就不会报错,如下:

  1. var arr = [];
  2. var sum = arr.reduce(function(prev, cur, index, arr) {
  3. console.log(prev, cur, index);
  4. return prev + cur;
  5. },0)
  6. console.log(arr, sum); // [] 0

所以一般来说我们提供初始值通常更安全

3、reduce的简单用法

当然最简单的就是我们常用的数组求和,求乘积了。

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

4、reduce的高级用法

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

```jsx 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}

  1. > 2)数组去重
  2. > ```jsx
  3. let arr = [1,2,3,4,4,1]
  4. let newArr = arr.reduce((pre,cur)=>{
  5. if(!pre.includes(cur)){
  6. return pre.concat(cur)
  7. }else{
  8. return pre
  9. }
  10. },[])
  11. console.log(newArr);// [1, 2, 3, 4]

(3)将二维数组转化为一维

  1. let arr = [[0, 1], [2, 3], [4, 5]]
  2. let newArr = arr.reduce((pre,cur)=>{
  3. return pre.concat(cur)
  4. },[])
  5. console.log(newArr); // [0, 1, 2, 3, 4, 5]

(3)将多维数组转化为一维

  1. let arr = [[0, 1], [2, 3], [4,[5,6,7]]]
  2. const newArr = function(arr){
  3. return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[])
  4. }
  5. console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]

(4)、对象里的属性求和

```jsx 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

  1. 神奇写法 提前使用
  2. <a name="0824b16b-1"></a>
  3. ### 02.典型例题
  4. <a name="b01e337d"></a>
  5. #### [682. 棒球比赛](https://leetcode-cn.com/problems/baseball-game/)
  6. <a name="ba515c95"></a>
  7. ##### 01.题目
  8. ```css
  9. 你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成,过去几回合的得分可能会影响以后几回合的得分。
  10. 比赛开始时,记录是空白的。你会得到一个记录操作的字符串列表 ops,其中 ops[i] 是你需要记录的第 i 项操作,ops 遵循下述规则:
  11. 整数 x - 表示本回合新获得分数 x
  12. "+" - 表示本回合新获得的得分是前两次得分的总和。题目数据保证记录此操作时前面总是存在两个有效的分数。
  13. "D" - 表示本回合新获得的得分是前一次得分的两倍。题目数据保证记录此操作时前面总是存在一个有效的分数。
  14. "C" - 表示前一次得分无效,将其从记录中移除。题目数据保证记录此操作时前面总是存在一个有效的分数。
  15. 请你返回记录中所有得分的总和。
  16. 示例 1:
  17. 输入:ops = ["5","2","C","D","+"]
  18. 输出:30
  19. 解释:
  20. "5" - 记录加 5 ,记录现在是 [5]
  21. "2" - 记录加 2 ,记录现在是 [5, 2]
  22. "C" - 使前一次得分的记录无效并将其移除,记录现在是 [5].
  23. "D" - 记录加 2 * 5 = 10 ,记录现在是 [5, 10].
  24. "+" - 记录加 5 + 10 = 15 ,记录现在是 [5, 10, 15].
  25. 所有得分的总和 5 + 10 + 15 = 30
  26. 示例 2:
  27. 输入:ops = ["5","-2","4","C","D","9","+","+"]
  28. 输出:27
  29. 解释:
  30. "5" - 记录加 5 ,记录现在是 [5]
  31. "-2" - 记录加 -2 ,记录现在是 [5, -2]
  32. "4" - 记录加 4 ,记录现在是 [5, -2, 4]
  33. "C" - 使前一次得分的记录无效并将其移除,记录现在是 [5, -2]
  34. "D" - 记录加 2 * -2 = -4 ,记录现在是 [5, -2, -4]
  35. "9" - 记录加 9 ,记录现在是 [5, -2, -4, 9]
  36. "+" - 记录加 -4 + 9 = 5 ,记录现在是 [5, -2, -4, 9, 5]
  37. "+" - 记录加 9 + 5 = 14 ,记录现在是 [5, -2, -4, 9, 5, 14]
  38. 所有得分的总和 5 + -2 + -4 + 9 + 5 + 14 = 27
  39. 示例 3:
  40. 输入:ops = ["1"]
  41. 输出:1

02.题解
  1. // /**
  2. // * @param {string[]} ops
  3. // * @return {number}
  4. // */
  5. var calPoints = function(ops) {
  6. var sum = 0;
  7. var res = []
  8. ops.forEach(item=>{
  9. if(item==='+'){
  10. res.push(+res[res.length-1]+res[res.length-2])
  11. }else if(item==='D'){
  12. res.push(+res[res.length-1] * 2)
  13. }else if(item==='C'){
  14. res.pop()
  15. }else{
  16. res.push(+item)
  17. }
  18. })
  19. return res.reduce((total,item)=>total+item)
  20. };

905. 按奇偶排序数组

  1. 给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素。
  2. 你可以返回满足此条件的任何数组作为答案。
  3. 示例:
  4. 输入:[3,1,2,4]
  5. 输出:[2,4,3,1]
  6. 输出 [4,2,3,1],[2,4,1,3] [4,2,1,3] 也会被接受。
  7. 提示:
  8. 1 <= A.length <= 5000
  9. 0 <= A[i] <= 5000
  1. 扁平化
  2. 解题思路
  3. 二维数组,0位数组放偶数,1位数字放奇数。扁平化
  1. var sortArrayByParity = function(A) {
  2. //注意 此处写法用到了剪头函数强行不写大括号 (item,index)=>(操作1,操作2,操作3,返回值)
  3. return A.reduce((p, v)=> (p[v & 1].push(v), p) , [[], []]).flat()
  4. };
  1. 遍历 偶数放前面 奇数放后面 +reduce
  1. /**
  2. * @param {number[]} nums
  3. * @return {number[]}
  4. */
  5. var sortArrayByParity = function(nums) {
  6. // return nums.reduce((p, v)=> (p[v & 1].push(v), p) , [[], []]).flat()
  7. // return nums.reduce((p, v)=> (p[v & 1].push(v),console.log(123), p) , [[], []]).flat()
  8. return nums.reduce((p,v)=>{
  9. v & 1 ? p.push(v) : p.unshift(v)
  10. return p
  11. },[])
  12. };

04.entries

Object.entries()

作用:返回的是一个数组,返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for…in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。Object.entries()返回一个数组,其元素是与直接在object上找到的可枚举属性键值对相对应的数组。属性的顺序与通过手动循环对象的属性值所给出的顺序相同。

语法:

  1. Object.entries(obj)
  • 参数:obj可以返回其可枚举属性的键值对的对象。
  • 返回值:给定对象自身可枚举属性的键值对数组。

实例:

  1. let person={name:'lisa',age:12,adress:'北京',show:function(){}};
  2. console.log(Object.entries(person));

004.提高效率写法 - 图3
上述例子返回的是一个二维数组。

因为返回的格式很像Map,所以我们可以把它改成Map格式,如下:

  1. var obj={name:"lisa",age:12};
  2. var m=new Map(Object.entries(obj));
  3. console.log(m);

004.提高效率写法 - 图4

Object.fromEntries()

作用:该方法把键值对列表转换为一个对象。
Object.fromEntries() 是 Object.entries 的反转。

语法

  1. Object.fromEntries(iterable);
  • 参数 iterable:可迭代对象,类似 Array 、 Map 或者其它实现了可迭代协议的对象。
  • 返回值:一个由该迭代对象条目提供对应属性的新对象。

实例
  1. let a=new Map([['name','张三'],['age','12'],['address','北京']]);
  2. let b=Object.fromEntries(a);
  3. console.log(b);

数组entries()

作用:
返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。

语法

  1. arr.entries()

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

实例

  1. let arr=["red","yellow","orange","pink"];
  2. let i=arr.entries();
  3. console.log(i.next().value);
  4. console.log(i.next().value);

可以使用for…of循环entries()

  1. let arr=["red","yellow","orange","pink"];
  2. let i=arr.entries();
  3. for(let e of i)
  4. {
  5. console.log(e);
  6. }

04.Map 实例的遍历方法

  1. keys():返回键名的遍历器。

  2. values():返回键值的遍历器。

  3. entries():返回所有成员的遍历器。

  4. forEach():遍历 Map 的所有成员。 ```javascript const map = new Map(); map.set(‘aaa’, 100); map.set(‘bbb’, 200);

for (let key of map.keys()) { console.log(key); } // “aaa” // “bbb”

for (let value of map.values()) { console.log(value); } // 100 // 200

for (let item of map.entries()) { console.log(item[0], item[1]); } // aaa 100 //…

  1. ```javascript
  2. entries()实例:
  3. var arr = ["a", "b", "c"];
  4. var eArr = arr.entries();
  5. console.log(eArr.next().value); // [0, "a"]
  6. console.log(eArr.next().value); // [1, "b"]
  7. console.log(eArr.next().value); // [2, "c"]

05.map

定义和用法 ——-输入一个数组 返回一个操作后的数组

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

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

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

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

```javascript //实例 //返回一个数组,数组中元素为原始数组的平方根:

var numbers = [4, 9, 16, 25];

function myFunction() { x = document.getElementById(“demo”) x.innerHTML = numbers.map(Math.sqrt); }

//输出结果为: //2,3,4,5

  1. > ```javascript
  2. //实用实例
  3. let books = [{
  4. name: "《算法导论》",
  5. beginDate: "2006-9",
  6. price: 85.00,
  7. count: 1
  8. },
  9. {
  10. name: "《UNIX编程艺术》",
  11. beginDate: "2006-2",
  12. price: 59.00,
  13. count: 1
  14. },
  15. {
  16. name: "《编程大全》",
  17. beginDate: "2008-10",
  18. price: 39.00,
  19. count: 1
  20. },
  21. {
  22. name: "《代码大全》",
  23. beginDate: "2006-3",
  24. price: 128.00,
  25. count: 1
  26. },
  27. ]
  28. let result = books.map(item => {
  29. return item.price * item.count
  30. })
  31. console.log(result);
  32. //输出结果为:
  33. //[ 85, 59, 39, 128 ]

MDN web docs上面说:

  1. map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

并举了个例子:

  1. var array1 = [1,4,9,16];
  2. const map1 = array1.map(x => x *2);
  3. console.log(map1);//[2,8,18,32]

打印结果为:

  1. Array [2,8,18,32]

而我这样写时:

```javascript var array1 = [1, 4, 9, 16];

const map1 = array1.map(x => { if (x == 4) { return x * 2; } });

console.log(map1);

  1. > 打印结果为:
  2. >
  3. > ```javascript
  4. Array [undefined, 8, undefined, undefined]

为什么会出现三个undefined呢?而不是我预期的[1,8,9,16]。

这样写只是增加了一个条件,即x的值为4时才乘以2,之所以会出现undefined,是因为map()方法创建了一个新数组,但新数组并不是在遍历完array1后才被赋值的,而是每遍历一次就得到一个值。所以,下面这样修改后就正确了:

```javascript var array1 = [1, 4, 9, 16];

const map1 = array1.map(x => { if (x == 4) { return x * 2; } return x; });

  1. > > <a name="2e78b2f0"></a>
  2. # [‘1‘,‘2‘,‘3‘].map(parseInt)结果讲解
  3. > > 一、前言<br />
  4. 这是一道前端面试题,先说结果:[1, NaN, NaN]
  5. > 二、为什么会是这个结果
  6. > 1. map函数
  7. >
  8. 将数组的每个元素传递给指定的函数处理,并返回处理后的数组,所以 ['1','2','3'].map(parseInt) 就是将字符串123作为元素;012作为下标分别调用 parseInt 函数。即分别求出 parseInt('1',0), parseInt('2',1), parseInt('3',2)的结果。
  9. > 2. parseInt函数(重点)
  10. >
  11. 概念:以第二个参数为基数来解析第一个参数字符串,通常用来做十进制的向上取整(省略小数)如:parseInt(2.7) //结果为2
  12. > 特点:接收两个参数parseInt(string,radix)
  13. > string:字母(大小写均可)、数组、特殊字符(不可放在开头,特殊字符及特殊字符后面的内容不做解析)的任意字符串,如 '2''2w''2!'
  14. > radix:解析字符串的基数,基数规则如下:
  15. > 1 区间范围介于2~36之间;
  16. > 2 当参数为 0parseInt() 会根据十进制来解析;
  17. > 3 如果忽略该参数,默认的基数规则:
  18. >
  1. 如果 string "0x" 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数;parseInt("0xf") //15
  2. 如果 string 0 开头,其后的字符解析为八进制或十六进制的数字;parseInt("08") //8
  3. 如果 string 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数;parseInt("88.99f") //88
  4. 只有字符串中的第一个数字会被返回。parseInt("10.33") //返回10;
  5. 开头和结尾的空格是允许的。parseInt(" 69 10 ") //返回69
  6. 如果字符串的第一个字符不能被转换为数字,返回 NaNparseInt("f") //返回NaN 而parseInt("f",16) //返回15
  1. > 三、再来分析一下结果<br />
  2. ['1','2','3'].map(parseInt)即
  3. > parseInt('1',0);radix 0parseInt() 会根据十进制来解析,所以结果为 1
  4. > parseInt('2',1);radix 1,超出区间范围,所以结果为 NaN
  5. > parseInt('3',2);radix 2,用2进制来解析,应以 0 1 开头,所以结果为 NaN
  6. > 四、parseInt方法解析的运算过程<br />
  7. parseInt('101.55',10); //以十进制解析,运算过程:向上取整数(不做四舍五入,省略小数),结果为 101。
  8. > parseInt('101',2); //以二进制解析,运算过程:1_2的2次方+0_2的1次方+1*2的0次方=4+0+1=5,结果为 5。
  9. > parseInt('101',8); //以八进制解析,运算过程:1_8的2次方+0_8的1次方+1*8的0次方=64+0+1=65,结果为 65。
  10. > parseInt('101',16); //以十六进制解析,运算过程:1_16的2次方+0_16的1次方+1*16的0次方=256+0+1=257,结果为 257
  11. > > <a name="c5627a9d"></a>
  12. ## 典型例题
  13. > ```css
  14. 我们要把给定的字符串 S 从左到右写到每一行上,每一行的最大宽度为100个单位,如果我们在写某个字母的时候会使这行超过了100 个单位,那么我们应该把这个字母写到下一行。我们给定了一个数组 widths ,这个数组 widths[0] 代表 'a' 需要的单位, widths[1] 代表 'b' 需要的单位,..., widths[25] 代表 'z' 需要的单位。
  15. 现在回答两个问题:至少多少行能放下S,以及最后一行使用的宽度是多少个单位?将你的答案作为长度为2的整数列表返回。
  16. 示例 1:
  17. 输入:
  18. widths = [10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]
  19. S = "abcdefghijklmnopqrstuvwxyz"
  20. 输出: [3, 60]
  21. 解释:
  22. 所有的字符拥有相同的占用单位10。所以书写所有的26个字母,
  23. 我们需要2个整行和占用60个单位的一行。
  24. 示例 2:
  25. 输入:
  26. widths = [4,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]
  27. S = "bbbcccdddaaa"
  28. 输出: [2, 4]
  29. 解释:
  30. 除去字母'a'所有的字符都是相同的单位10,并且字符串 "bbbcccdddaa" 将会覆盖 9 * 10 + 2 * 4 = 98 个单位.
  31. 最后一个字母 'a' 将会被写到第二行,因为第一行只剩下2个单位了。
  32. 所以,这个答案是2行,第二行有4个单位宽度。
  1. 1.将单词中的每一个字母转换成对应的数字
  2. 2.定义两个变量,用来存储行数,和最后的余数
  3. 3.逢百进1,默认就有一行

```javascript /**

  • @param {number[]} widths
  • @param {string} s
  • @return {number[]} */ var numberOfLines = function(widths, s) { const sList = s.split(“”).map(item=>{
    1. return widths[item.charCodeAt() - 97]
    })
  1. let counts = 1
  2. let summary = 0
  3. // console.log("sList:", sList)
  4. for(j=0;j < sList.length ;j++) {
  5. const item = sList[j]
  6. // const nextItem = sList[j-1]
  7. if (summary + item <= 100 ) {
  8. summary += item
  9. } else {
  10. counts += 1
  11. summary = item
  12. }
  13. }
  14. return [counts,summary]

};

  1. <a name="d01c5e7d"></a>
  2. ## 06.every和some
  3. [JS中every()和some()的用法](https://www.cnblogs.com/yourstars/p/7822858.html)
  4. every()与some()方法都是JS中数组的迭代方法。
  5. every()是对数组中每一项运行给定函数,如果该函数对**每一项**返回true,才返回true。 有意一项不满足。返回false
  6. some()是对数组中每一项运行给定函数,如果该函数对**任一项**返回true,就返回true。
  7. ```css
  8. some() 方法会对数组中的每一项进行遍历,只要有一个元素符合条件,就返回true,且==剩余的元素不会再进行检测==,否则就返回false。
  9. every() 方法会对数组中的每一项进行遍历,只有所有元素都符合条件时,才返回true,如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且==剩余的元素不会再进行检测==。 如果有一个元素不返回值 自动返回false
  • 总结:
    方法区别
    every() 每一项都返回true才返回true 找到最终结构就停止
    some() 只要有一项返回true就返回true 找到最终结构就停止
  1. var arr = [ 1, 2, 3, 4, 5, 6 ];
  2. console.log( arr.some( function( item, index, array ){
  3. console.log( 'item=' + item + ',index='+index+',array='+array );
  4. return item > 3;
  5. }));
  6. //output-->>
  7. // item=1,index=0,array=1,2,3,4,5,6
  8. // item=2,index=1,array=1,2,3,4,5,6
  9. // item=3,index=2,array=1,2,3,4,5,6
  10. // item=4,index=3,array=1,2,3,4,5,6
  11. // true
  12. console.log( arr.every( function( item, index, array ){
  13. console.log( 'item=' + item + ',index='+index+',array='+array );
  14. return item > 3;
  15. }));
  16. //output-->>
  17. // item=1,index=0,array=1,2,3,4,5,6
  18. // false

实例1 every判断单调序列 有一个不满足则返回false 注意 如果有一个元素不返回值 自动返回false

  1. /**
  2. * @param {number[]} nums
  3. * @return {boolean}
  4. */
  5. var isMonotonic = function(nums) {
  6. return nums.every((item,index)=>{
  7. if(index<nums.length-1){
  8. if(nums[0]>=nums[nums.length-1]){
  9. if(item>=nums[index+1]){
  10. return true
  11. }else{
  12. console.log('有元素失败',index)
  13. return false
  14. }
  15. }
  16. if(nums[0]<=nums[nums.length-1]){
  17. if(item<=nums[index+1]){
  18. return true
  19. }else{
  20. return false
  21. }
  22. }
  23. }else{
  24. return true
  25. }
  26. }
  27. )
  28. };

典型例题01.211. 添加与搜索单词 - 数据结构设计

```css 请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。

实现词典类 WordDictionary :

WordDictionary() 初始化词典对象 void addWord(word) 将 word 添加到数据结构中,之后可以对它进行匹配 bool search(word) 如果数据结构中存在字符串与 word 匹配,则返回 true ;否则,返回 false 。word 中可能包含一些 ‘.’ ,每个 . 都可以表示任何一个字母。

示例:

输入: [“WordDictionary”,”addWord”,”addWord”,”addWord”,”search”,”search”,”search”,”search”] [[],[“bad”],[“dad”],[“mad”],[“pad”],[“bad”],[“.ad”],[“b..”]] 输出: [null,null,null,null,false,true,true,true]

解释: WordDictionary wordDictionary = new WordDictionary(); wordDictionary.addWord(“bad”); wordDictionary.addWord(“dad”); wordDictionary.addWord(“mad”); wordDictionary.search(“pad”); // return False wordDictionary.search(“bad”); // return True wordDictionary.search(“.ad”); // return True wordDictionary.search(“b..”); // return True

提示:

1 <= word.length <= 500 addWord 中的 word 由小写英文字母组成 search 中的 word 由 ‘.’ 或小写英文字母组成 最多调用 50000 次 addWord 和 search

  1. > 方法1 使用数组封装
  2. > ```javascript
  3. var WordDictionary = function() {
  4. this.item = []
  5. };
  6. /**
  7. * @param {string} word
  8. * @return {void}
  9. */
  10. WordDictionary.prototype.addWord = function(word) {
  11. this.item.push(word)
  12. };
  13. /**
  14. * @param {string} word
  15. * @return {boolean}
  16. */
  17. WordDictionary.prototype.search = function(word) {
  18. return this.item.some(element=>{//some 有一个符合条件即返回true 否则遍历全部数据后返回false
  19. if(element === word){
  20. return true
  21. }else{
  22. if(element.length==word.length){
  23. return element.split('').every((char,index)=>{//every 全部符合条件才返回true
  24. return char===word[index] || word[index]=== '.'
  25. })
  26. }else{
  27. return false
  28. }
  29. }
  30. })
  31. };
  32. /**
  33. * Your WordDictionary object will be instantiated and called as such:
  34. * var obj = new WordDictionary()
  35. * obj.addWord(word)
  36. * var param_2 = obj.search(word)
  37. */

02.常用语句

01.快速求取数组最大值

  1. let array = [1,2,3]
  2. Math.max(...array)

03.白嫖笔记

今天我们来看点基础的知识,看看JavaScript中有些循环遍历方法:

004.提高效率写法 - 图5

一、数组遍历方法

1. forEach()

forEach 方法用于调用数组的每个元素,并将元素传递给回调函数。数组中的每个值都会调用回调函数。其语法如下:

  1. array.forEach(function(currentValue, index, arr), thisValue)

该方法的第一个参数为回调函数,是必传的,它有三个参数:

  • currentValue:必需。当前元素

  • index:可选。当前元素的索引值。

  • arr:可选。当前元素所属的数组对象

  1. let arr = [1,2,3,4,5]
  2. arr.forEach((item, index, arr) => {
  3. console.log(index+":"+item)
  4. })

该方法还可以有第二个参数,用来绑定回调函数内部this变量(前提是回调函数不能是箭头函数,因为箭头函数没有this):

  1. let arr = [1,2,3,4,5]
  2. let arr1 = [9,8,7,6,5]
  3. arr.forEach(function(item, index, arr){
  4. console.log(this[index]) // 9 8 7 6 5
  5. }, arr1)

注意:

  • forEach 方法不会改变原数组,也没有返回值;

  • forEach无法使用 break,continue 跳出循环,使用 return 时,效果和在 for 循环中使用 continue 一致;

  • forEach 方法无法遍历对象,仅适用于数组的遍历。

2. map()

map() 方法会返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。该方法按照原始数组元素顺序依次处理元素。其语法如下:

  1. array.map(function(currentValue,index,arr), thisValue)

该方法的第一个参数为回调函数,是必传的,它有三个参数:

  • currentValue:必须。当前元素的值;

  • index:可选。当前元素的索引值;

  • arr:可选。当前元素属于的数组对象。

  1. let arr = [1, 2, 3];
  2. arr.map(item => {
  3. return item + 1;
  4. })
  5. // 输出结果: [2, 3, 4]

该方法的第二个参数用来绑定参数函数内部的this变量,是可选的:

  1. let arr = ['a', 'b', 'c'];
  2. [1, 2].map(function (e) {
  3. return this[e];
  4. }, arr)
  5. // 输出结果: ['b', 'c']

该方法还可以进行链式调用:

  1. let arr = [1, 2, 3];
  2. arr.map(item => item + 1).map(item => item + 1)
  3. // 输出结果: [3, 4, 5]

注意:

  • map 方法不会对空数组进行检测;

  • map 方法遍历数组时会返回一个新数组,不会改变原始数组

  • map 方法有返回值,可以return出来,map的回调函数中支持return返回值;

  • map 方法无法遍历对象,仅适用于数组的遍历。

3. for of

for...of 语句创建一个循环来迭代可迭代的对象。在 ES6 中引入的 for...of 循环,以替代 for...inforEach() ,并支持新的迭代协议。其语法如下:

  1. for (variable of iterable) {
  2. statement
  3. }

该方法有两个参数:

  • variable:每个迭代的属性值被分配给该变量。
  • iterable:一个具有可枚举属性并且可以迭代的对象。

该方法允许获取对象的键值:

  1. let arr = [
  2. {id:1, value:'hello'},
  3. {id:2, value:'world'},
  4. {id:3, value:'JavaScript'}
  5. ]
  6. for (let item in arr) {
  7. console.log(item);
  8. }
  9. // 输出结果:0 1 2

注意:

  • for of 方法只会遍历当前对象的属性,不会遍历其原型链上的属性;

  • for of 方法适用遍历 数组/ 类数组/字符串/map/set 等拥有迭代器对象的集合;

  • for of 方法不支持遍历普通对象,因为其没有迭代器对象。如果想要遍历一个对象的属性,可以用 for in 方法;

  • 可以使用break、continue、return来中断循环遍历;

4. filter()

filter不会修改原数组

filter()方法用于过滤数组,满足条件的元素会被返回。它的参数是一个回调函数,所有数组元素依次执行该函数,返回结果为true的元素会被返回,如果没有符合条件的元素,则返回空数组。其语法如下:

  1. array.filter(function(currentValue,index,arr), thisValue)

该方法的第一个参数为回调函数,是必传的,它有三个参数:

  • currentValue:必须。当前元素的值;

  • index:可选。当前元素的索引值;

  • arr:可选。当前元素属于的数组对象。

  1. const arr = [1, 2, 3, 4, 5]
  2. arr.filter(item => item > 2)
  3. // 输出结果:[3, 4, 5]

同样,它也有第二个参数,用来绑定参数函数内部的this变量。

可以使用filter()方法来移除数组中的undefined、null、NAN等值:

  1. let arr = [1, undefined, 2, null, 3, false, '', 4, 0]
  2. arr.filter(Boolean)
  3. // 输出结果:[1, 2, 3, 4]

注意:

  • filter 方法会返回一个新的数组,不会改变原数组;

  • filter 方法不会对空数组进行检测;

  • filter 方法仅适用于检测数组。

5. some()、every()

some() 方法会对数组中的每一项进行遍历,只要有一个元素符合条件,就返回true,且剩余的元素不会再进行检测,否则就返回false。

every() 方法会对数组中的每一项进行遍历,只有所有元素都符合条件时,才返回true,如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。其语法如下:

两者的语法如下:

  1. array.some(function(currentValue,index,arr),thisValue)
  2. array.every(function(currentValue,index,arr), thisValue)

两个方法的第一个参数为回调函数,是必传的,它有三个参数:

  • currentValue:必须。当前元素的值;

  • index:可选。当前元素的索引值;

  • arr:可选。当前元素属于的数组对象。

  1. let arr = [1, 2, 3, 4, 5]
  2. arr.some(item => item > 4)
  3. // 输出结果: true
  4. let arr = [1, 2, 3, 4, 5]
  5. arr.every(item => item > 0)
  6. // 输出结果: true

注意:

  • 两个方法都不会改变原数组,会返回一个布尔值;

  • 两个方法都不会对空数组进行检测;

  • 两个方法都仅适用于检测数组。

6. reduce()、reduceRight()

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。reduce() 可以作为一个高阶函数,用于函数的 compose。其语法如下:

  1. array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

reduce 方法会为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,回调函数接受四个参数:

  • total:上一次调用回调返回的值,或者是提供的初始值(initialValue);

  • currentValue:当前被处理的元素;

  • currentIndex:当前元素的索引;

  • arr:当前元素所属的数组对象。

该方法的第二个参数是 initialValue,表示传递给函数的初始值 (作为第一次调用 callback 的第一个参数):

  1. let arr = [1, 2, 3, 4]
  2. let sum = arr.reduce((prev, cur, index, arr) => {
  3. console.log(prev, cur, index);
  4. return prev + cur;
  5. })
  6. console.log(arr, sum);

输出结果:

  1. 1 2 1
  2. 3 3 2
  3. 6 4 3
  4. [1, 2, 3, 4] 10

再来加一个初始值试试:

  1. let arr = [1, 2, 3, 4]
  2. let sum = arr.reduce((prev, cur, index, arr) => {
  3. console.log(prev, cur, index);
  4. return prev + cur;
  5. }, 5)
  6. console.log(arr, sum);

输出结果:

  1. 5 1 0
  2. 6 2 1
  3. 8 3 2
  4. 11 4 3
  5. [1, 2, 3, 4] 15

由此可以得出结论:如果没有提供初始值initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供了初始值initialValue,从索引0开始执行

reduceRight() 方法和的reduce()用法几乎一致,只是该方法是对数组进行倒序遍历的,而reduce()方法是正序遍历的。

  1. let arr = [1, 2, 3, 4]
  2. let sum = arr.reduceRight((prev, cur, index, arr) => {
  3. console.log(prev, cur, index);
  4. return prev + cur;
  5. }, 5)
  6. console.log(arr, sum);

输出结果:

  1. 5 4 3
  2. 9 3 2
  3. 12 2 1
  4. 14 1 0
  5. [1, 2, 3, 4] 15

注意:

  • 两个方法都不会改变原数组;

  • 两个方法如果添加初始值,就会改变原数组,会将这个初始值放在数组的最后一位;

  • 两个方法对于空数组是不会执行回调函数的。

7. find()、findIndex()

find() 方法返回通过函数内判断的数组的第一个元素的值。当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素,之后的值不会再调用执行函数。如果没有符合条件的元素返回 undefined。

findIndex() 方法返回传入一个测试函数符合条件的数组第一个元素位置(索引)。当数组中的元素在函数条件时返回 true 时, findIndex() 返回符合条件的元素的索引位置,之后的值不会再调用执行函数。如果没有符合条件的元素返回 -1。

两个方法的语法如下:

  1. array.find(function(currentValue, index, arr),thisValue)
  2. array.findIndex(function(currentValue, index, arr), thisValue)

两个方法的第一个参数为回调函数,是必传的,它有三个参数:

  • currentValue:必需。当前元素;

  • index:可选。当前元素的索引;

  • arr:可选。当前元素所属的数组对象。

  1. let arr = [1, 2, 3, 4, 5]
  2. arr.find(item => item > 2)
  3. // 输出结果: 3
  4. let arr = [1, 2, 3, 4, 5]
  5. arr.findIndex(item => item > 2)
  6. // 输出结果: 2

find()findIndex()两个方法几乎一样,只是返回结果不同:

  • find():返回的是第一个符合条件的值;
  • findIndex:返回的是第一个返回条件的值的索引值。

注意:

  • 两个方法对于空数组,函数是不会执行的;
  • 两个方法否不会改变原数组。

8. keys()、values()、entries()

三个方法都返回一个数组的迭代对象,对象的内容不太相同:

  • keys() 返回数组的索引值;

  • values() 返回数组的元素;

  • entries() 返回数组的键值对。

三个方法的语法如下:

  1. array.keys()
  2. array.values()
  3. array.entries()

这三个方法都没有参数:

  1. let arr = ["Banana", "Orange", "Apple", "Mango"];
  2. const iterator1 = arr.keys();
  3. const iterator2 = arr.values()
  4. const iterator3 = arr.entries()
  5. for (let item of iterator1) {
  6. console.log(item);
  7. }
  8. // 输出结果: 0 1 2 3
  9. for (let item of iterator2) {
  10. console.log(item);
  11. }
  12. // 输出结果: Banana Orange Apple Mango
  13. for (let item of iterator3) {
  14. console.log(item);
  15. }
  16. // 输出结果:[0, 'Banana'] [1, 'Orange'] [2, 'Apple'] [3, 'Mango']

总结:

方法 是否改变原数组 特点
forEach() 没有返回值
map() 有返回值,可链式调用
for of for…of遍历具有Iterator迭代器的对象的属性,返回的是数组的元素、对象的属性值,不能遍历普通的obj对象,将异步循环变成同步循环
filter() 过滤数组,返回包含符合条件的元素的数组,可链式调用
every()、some() some()只要有一个是true,便返回true;而every()只要有一个是false,便返回false.
find()、findIndex() find()返回的是第一个符合条件的值;findIndex()返回的是第一个返回条件的值的索引值
reduce()、reduceRight() reduce()对数组正序操作;reduceRight()对数组逆序操作
keys()、values()、entries() keys() 返回数组的索引值;values() 返回数组元素;entries() 返回数组的键值对。

二、对象遍历方法

1. for in

for…in 主要用于循环对象属性。循环中的代码每执行一次,就会对对象的属性进行一次操作。其语法如下:

  1. for (var in object) {
  2. 执行的代码块
  3. }

其中两个参数:

  • var:必须。指定的变量可以是数组元素,也可以是对象的属性。
  • object:必须。指定迭代的的对象。
  1. var obj = {a: 1, b: 2, c: 3};
  2. for (var i in obj) {
  3. console.log('键名:', i);
  4. console.log('键值:', obj[i]);
  5. }

输出结果:

  1. 键名: a
  2. 键值: 1
  3. 键名: b
  4. 键值: 2
  5. 键名: c
  6. 键值: 3

注意:

  • for in 方法不仅会遍历当前的对象所有的可枚举属性,还会遍历其原型链上的属性。

2. Object.keys()、Object.values()、Object.entries()

这三个方法都用来遍历对象,它会返回一个由给定对象的自身可枚举属性(不含继承的和Symbol属性)组成的数组,数组元素的排列顺序和正常循环遍历该对象时返回的顺序一致,这个三个元素返回的值分别如下:

  • Object.keys():返回包含对象键名的数组;

  • Object.values():返回包含对象键值的数组;

  • Object.entries():返回包含对象键名和键值的数组。

  1. let obj = {
  2. id: 1,
  3. name: 'hello',
  4. age: 18
  5. };
  6. console.log(Object.keys(obj)); // 输出结果: ['id', 'name', 'age']
  7. console.log(Object.values(obj)); // 输出结果: [1, 'hello', 18]
  8. console.log(Object.keys(obj)); // 输出结果: [['id', 1], ['name', 'hello'], ['age', 18]

注意

  • Object.keys()方法返回的数组中的值都是字符串,也就是说不是字符串的key值会转化为字符串。
  • 结果数组中的属性值都是对象本身可枚举的属性,不包括继承来的属性。

3. Object.getOwnPropertyNames()

Object.getOwnPropertyNames()方法与Object.keys()类似,也是接受一个对象作为参数,返回一个数组,包含了该对象自身的所有属性名。但它能返回不可枚举的属性。

  1. let a = ['Hello', 'World'];
  2. Object.keys(a) // ["0", "1"]
  3. Object.getOwnPropertyNames(a) // ["0", "1", "length"]

这两个方法都可以用来计算对象中属性的个数:

  1. var obj = { 0: "a", 1: "b", 2: "c"};
  2. Object.getOwnPropertyNames(obj) // ["0", "1", "2"]
  3. Object.keys(obj).length // 3
  4. Object.getOwnPropertyNames(obj).length // 3

4. Object.getOwnPropertySymbols()

Object.getOwnPropertySymbols() 方法返回对象自身的 Symbol 属性组成的数组,不包括字符串属性:

  1. let obj = {a: 1}
  2. // 给对象添加一个不可枚举的 Symbol 属性
  3. Object.defineProperties(obj, {
  4. [Symbol('baz')]: {
  5. value: 'Symbol baz',
  6. enumerable: false
  7. }
  8. })
  9. // 给对象添加一个可枚举的 Symbol 属性
  10. obj[Symbol('foo')] = 'Symbol foo'
  11. Object.getOwnPropertySymbols(obj).forEach((key) => {
  12. console.log(obj[key])
  13. })
  14. // 输出结果:Symbol baz Symbol foo

5. Reflect.ownKeys()

Reflect.ownKeys() 返回一个数组,包含对象自身的所有属性。它和Object.keys()类似,Object.keys()返回属性key,但不包括不可枚举的属性,而Reflect.ownKeys()会返回所有属性key:

  1. var obj = {
  2. a: 1,
  3. b: 2
  4. }
  5. Object.defineProperty(obj, 'method', {
  6. value: function () {
  7. alert("Non enumerable property")
  8. },
  9. enumerable: false
  10. })
  11. console.log(Object.keys(obj))
  12. // ["a", "b"]
  13. console.log(Reflect.ownKeys(obj))
  14. // ["a", "b", "method"]

注意:

  • Object.keys() :相当于返回对象属性数组;
  • Reflect.ownKeys() :相当于 Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)

总结:

对象方法 遍历基本属性 遍历原型链 遍历不可枚举属性 遍历Symbol
for in
Object.keys()
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Reflect.ownKeys()

三、其他遍历方法

1. for

for循环是应该是最常见的循环方式了,它由三个表达式组成,分别是声明循环变量、判断循环条件、更新循环变量。这三个表达式用分号分隔。可以使用临时变量将数组的长度缓存起来,避免重复获取数组长度,当数组较大时优化效果会比较明显。

  1. const arr = [1,2,3,4,5]
  2. for(let i = 0, len = arr.length; i < len; i++ ){
  3. console.log(arr[i])
  4. }

在执行的时候,会先判断执行条件,再执行。for循环可以用来遍历数组,字符串,类数组,DOM节点等。可以改变原数组。

2. while

while循环中的结束条件可以是各种类型,但是最终都会转为布尔值,转换规则如下。

  • Boolean:true为真,false为假;

  • String:空字符串为假,所有非空字符串为真;

  • Number:0为假,非0数字为真;

  • null/Undefined/NaN:全为假;

  • Object:全为真。

  1. let num = 1;
  2. while (num < 10){
  3. console.log(num);
  4. num ++;
  5. }

whilefor一样,都是先判断,再执行。只要指定条件为 true,循环就可以一直执行代码。

3. do / while

该方法会先执行再判断,即使初始条件不成立,do/while循环也至少会执行一次。

  1. let num = 10;
  2. do
  3. {
  4. console.log(num);
  5. num--;
  6. }
  7. while(num >= 0);
  8. console.log(num); //-1

不建议使用do / while来遍历数组。

4. for await of

for await...of方法被称为异步迭代器,该方法是主要用来遍历异步对象。它是ES2018中引入的方法。

for await...of 语句会在异步或者同步可迭代对象上创建一个迭代循环,包括 String,Array,类数组,Map, Set和自定义的异步或者同步可迭代对象。这个语句只能在 async function内使用:

  1. function Gen (time) {
  2. return new Promise((resolve,reject) => {
  3. setTimeout(function () {
  4. resolve(time)
  5. },time)
  6. })
  7. }
  8. async function test () {
  9. let arr = [Gen(2000),Gen(100),Gen(3000)]
  10. for await (let item of arr) {
  11. console.log(Date.now(),item)
  12. }
  13. }
  14. test()

输出结果:

004.提高效率写法 - 图6