Teach you to make good use of Javascript array

Original link: https: //juejin.im/post/5d9769b26fb9a04df26c1b89

As one standard Javascript object underlying the array and is very useful data structure. Although the structure is simple, but not simple good use, including when I started learning JS to see a bunch of native method is very deceived, how can there be so many ways. And an array of various methods have their own characteristics and usage scenarios, if you are still in for a shuttle loop phase, which is the array element stitching, traversal operations are done with a for loop stage, then this article It is for you, or you can push to force your pit colleagues ︿ (¯)¯) ︿.

Building Arrays

Literal form

A principle: can type literal as possible with a literal construction of the structure . For example, one vote basic types of objects, arrays, strings, etc., [1, 2, 3]than new Array(1, 2, 3), the degree of readability and streamlining are good. Each comma array of spaces are added, want to be good programmers have to pay attention to detail.

Operator binding literal extension

The so-called extended operators are the three points that operators: ...when we construct a new array of other elements in the array need time, you can use the extended operator.

// 一个无副作用的 push
Array.prototype.purePush = function(...elements) { return [...this, ...elements]; }; console.log([1, 3, 1, 4].purePush(5, 2, 0)); // => [ 1, 3, 1, 4, 5, 2, 0 ]  复制代码

An array of array-turn

ES5 version

There are many arguments, nodelist and other types of arrays into an array of ways, the first time I saw the following way such ES5 class array transfer array is also very ignorant force.

function testArrayLikeToArray () {
   var args; 

  the console.log (arguments); // => {[the Iterator] 0: 'A',. 1: 'B', 2: 'C', [the Symbol (Symbol.iterator)]: [[lambda]: values]}  
  // can be accessed through the index and can also access length 
  the console.log (arguments [0]); // => A 
  the console.log (the arguments.length);
   // return false description is not an array 
  the console.log (Array.isArray (arguments)); // => to false 

  args = Array.prototype.slice.call (arguments); 
  the console.log (args); // => [ 'A', 'B', 'C'] 
  the console.log (Array.isArray (args)); // => to true 
}

testArrayLikeToArray('a', 'b', 'c');

 

Mainly this line of code:

args = Array.prototype.slice.call(arguments);

 

Array.prototypeExamples of the array can be directly used as an empty array literal []instead, as long as the acquired slice array prototype can. The above code will point to this slice of arguments why the function can return an array corresponding to an array of classes it?

I have not studied the specific implementation of the slice, I guess this is the following:

Array.prototype.mySlice = function(start=0, end) {
    const array = this;
    const end = end === undefined ? array.length : end;
    
    const resultArray = [];
    if (array.length === 0) return resultArray;
    for (let index = start; index < end; index++) {
        resultArray.push(array[index]);
    }
    return resultArray;
}

 

 

I would like to achieve internal slice probably be like me, like the above code requires only a length property, through the elements return the new array, so when you call the slice to this point to an array of classes to work properly.

Use Array.from

args = Array.from(arguments);

Extended operator
args = [...args];

 

Array.from and extended operator action object may be an iterative array of objects and classes, the array type may be properly converted. Recommended use of the latter two ES6, we learn new knowledge is make use of them, if not brought with it no sense, we do not easily remember.

Turn an array of objects

In normal development, we often need keys to objects, values, entries operation corresponding to the Object method is Object.keys, Object.values, Object.entries. This API returns three arrays are not like Map return Iterator, because I think the reason is because the object is generally key-value pairs are limited, less direct returns an array and does not take up much memory, but not the same as Map , map generally serve a large number of key-value pairs, if the direct returns an array as a waste of memory, and the use of iterators is more appropriate, because the iterator does not produce an array, it is traversing the original iterable. Here direct look at a few cases like:

Object.keys()

// determines whether the object is empty 
const isEmpty = (obj) => obj.keys () length == 0.!;

 

Object.values()

// string array turn 
the console.log (Object.values ( 'ABC')); // => [ 'A', 'B', 'C']

 

Traverse the object

Some may still use this way to traverse the following objects:

const me = {
  name: 'ly',
  age: 21,
};

me.__proto__.sex = 'man';

for (const key in me) {
  me.hasOwnProperty(key) && console.log(`${key}: ${me[key]}`);
}

// =>
// name: ly
// age: 21

 

It is too low, it is recommended that the use of the following methods:

const me = {
  name: 'ly',
  age: 21,
};

me.__proto__.sex = 'man';

// 命令式风格
for (const [key, value] of Object.entries(me)) {
  console.log(`${key}: ${value}`);
}

// 函数式风格
// Object.entries(me).forEach(([key, value]) => console.log(`${key}: ${value}`));

// =>
// name: ly
// age: 21

 

This approach takes advantage of Object.entries above so that we can get an array of key-value pairs in the array combine for of circulation and deconstruction let you access key and value directly in the loop.

Set and Map transfer array

can be seen as the key and the same set value of the Map, Map into an array or using map.keys (), map.values ​​(), map.entries (), have said before, Map three interfaces is returned iterator, and It is not an array, but Array.from and extended operation and can be iterator class and an array into an array, so, usually Map into an array like this:

LANGUAGE_CODE_MAPPER = const Object.freeze (
   new new the Map ([[ 'EN', 'Dictionary Dictionary English'], [ 'ZH', 'Chinese'], [ 'JA', 'Japanese'], [ 'fr', 'French' ] ]) 
); 

// React rendering options, of course, where the extended operator can also be used instead of Array.from 
// first iterator acquired, then the iterator into an array 
. const options = [... LANGUAGE_CODE_MAPPER.entries ( )] map ( ([code, language]) = > <Option value = {{key}}> {{language}} </ Option>)

 

Turn an array of strings

There are many ways, already mentioned above can be used Object.values ​​(), since the string is Iterator, it may also be used and the extended operator to Array.from conversion.

console.log(Array.from('abcd'));
console.log([...'abcd']);
console.log('abcd'.split(''));
console.log([].slice.call('abcd'));
// 使用 Reflect.apply 改变 slice 函数指向
console.log(Reflect.apply([].slice, 'abcd', []));

// =>
// [ 'a', 'b', 'c', 'd' ]
// [ 'a', 'b', 'c', 'd' ]
// [ 'a', 'b', 'c', 'd' ]
// [ 'a', 'b', 'c', 'd' ]
// [ 'a', 'b', 'c', 'd' ]

 

While writing a lot, but consider it a good split, compatible device, readability, simplicity is not bad. Here are so many ways to write down ideas just to extend it, in fact there are a lot of ways, as a good programmer should learn to summarize, summarize best practices and applied in the usual coding.

Construction elements of redundant array

You can use array.fill:

const arr = Array(6).fill(6);
console.log(arr); // => [ 6, 6, 6, 6, 6, 6 ]

 

Consecutive integers array configuration

Array.from is also a higher-order functions, we can accept a function to process each element.

// length set to an integer number of your needs to be acquired, index + 1 can be replaced with a size of the first number you want to set 
const continuousIntegers = Array.from ({length: 10}, (__, index) => + index. 1 ); 
the console.log (continuousIntegers); // => [. 1, 2,. 3,. 4,. 5,. 6,. 7,. 8,. 9, 10] 

 

Construct successive letters

console.log(Array.from({ length: 27 }, (__, index) => String.fromCodePoint('a'.codePointAt(0) + index)));
// =>
// ['a'
// ...
// 'z']

 

new Array(length), Array(length), Array.of(length) 有啥区别?

new Array (6) results equal Array (6), but Array.of (6) is returned to 6 as a first element of the array.

 

new Array(), Array(), Array.of

 

Array (n) and Array.from ({length: n}) any difference?

Test console, at a glance, Array.from ({length: 4}) returns an array of four elements comprising a value is undefined, and the Array (4) returns an array of elements comprises four empty.

Speaking of which you may not understand empty elements and undefined What is the difference, empty elements can not be forEach, map and other functions to traverse to, so when I construct the array can be traversed using Array.from (length: n) and not Array (n), for example, the above configuration examples consecutive integers and letters, you replace Array (length) can not.

 

array

 

Array Methods

There are many ways an array, to the knowledge remember the prison, in addition to more thinking and more use, learn classification is also very important.

classification

The use according to points

  1. push / pop operations end of the array, in fact it can be said stack related methods
  2. shift / unshift operation of the first unit array, you say the combination can actually turn the array as a stack.
  3. splice 唯一可以删除插入元素的方法,当你要删除元素或者在哪个位置插入一个元素,找它准没错
  4. slice 切片操作,或者说取原数组的连续子集,虽然不如 python 那样方便还可以传一个 step 参数,但是一般够用
  5. indexOf/lastIndexOf /includes/find/findIndex 查找元素
  6. join 拼接成字符串的,少数和字符串操作相关的方法之一
  7. isArray 判断是否是个数组,面试经常问的一道非常非常非常基础的问题
  8. of/from 构造或者转换数组的
  9. reverse 翻转数组的,调用之后会改变原数组的函数不多,他也是一个
  10. sort 其实可以和 reverse 放一类,reverse 叫倒序,sort 排序
  11. keys/values/entries 和 Map 类似,返回的都是 Iterator
  12. flat 数组扁平化
  13. concat 拼接数组,因为效果是将数组参数打平后拼接,所以可以用来实现扁平化
  14. forEach/filter/map/reduce/reduceRight/some/every 用于集合变换的,后面单独聊聊

按照参数类型来分

  1. forEach/filter/map 等接受函数作为参数的高阶函数,这些方法大多数参数都是(value, index, self),即当前遍历的原素的值,索引,数组本身。
  2. 其它

这么多方法该如何选择?

这部分内容是写给初学者的,读者选择性阅读。

上面列了这么多,按照用途分类我都列了 14 类,要是像 JSON 那样就 stringify 和 parse 两个常用的方法那该多爽。我刚开始学习 js 数组的时候也很郁闷,怎么这么多的方法。其实没关系,方法多是好事,方法意味着方便,合适的场景选择合适的方法可以大大减少我们的代码量,可读性也会提高不少。

回到标题,这么多方法该如何选择呢?首先,我觉得作为一个初学者,你好歹把这些方法挨个看一边,知道它们是干嘛用的,它们的用法是怎么样的。我每次学习一门新语言的时候,都会花一到两周的时间去学习基础语法,基础必须扎实,你绝大数情况写的代码都是基础语法,其实我也觉得 js 语法很简单,我当初做笔记就有点烦,觉得写那些以前 java, python 就搞过的 map,slice 没啥意思,写个锤子,但是我还是认真的每个 API 都自己敲一遍,有些坑你自己不敲一遍你永远不会知道,你不敲一下 typeof null 你还真想不到这笔返回 'object'。

过一遍之后当然是忘得差不多了,没关系,有个印象就行,好像那个 reverse 函数是用来翻转数组的,但是到底是返回新数组还是直接改变原数组,这个忘了,有关系吗?没关系的其实,记住翻转就够了,至于会不会返回新数组,临时测试一下就好了。

然后就是多敲代码,多用。前面也说了,学习新语法你觉得有用的就一定要用上,比如你以前不知道可以用 forEach 这个高阶函数来遍历数组,你学了之后,觉得这个不错哦,那你就用上呗,下次敲代码,碰到一个场景你要遍历一个数组,就用 forEach,就不要去用 for 循环了。当然了可能有些情况下 forEach 并不适用比如你要提前 break,诶,你看,你这不就发现 forEach 的一个坑,不能提前退出,面试也经常会问 forEach 遍历和 for 循环有啥区别啊,这不就是一个区别喽,for 循环可以使用 break 提前退出。重要的是说三遍:

学了新知识,一定要用,

学了新知识,一定要用,

学了新知识,一定要用

我每次在一篇文章中 get 到新技能之后,比如之前看人家用正则配合 map 处理多条件分支,我在项目中碰到多分支的情况就会考虑用上。如果学了用不上咋办,忘了它,都用不上学它干嘛,比如学 Java web 现在还学 jsp,学 js 你去了解 with 语句有啥用啊?包括之前在知乎看到有人发了个贴说面试官问它原型链,其实我觉得问原型链除非人家简历写着熟悉或精通原生 js,你问人家原型链,那无可厚非,但是就因为人家原型链没搞明白就否认人家,认为人家技术不行,我觉得这是不应该的,你自己平时写业务代码需要用上原型链的机会多不多没B数吗?

其实上面说的还不是最关键的,最关键的是学会思考,学会总结,思考多了,总结多了,自然就能如鱼得水,从容应对。你在用那些方法的时候有没有像我在分类中描述的那样总结出那些方法各自的用途?如果你要在删除某个索引位置的元素或者在某个索引位置插入元素那肯定是用 splice 了,有没有总结过 forEach,map,filter,reduce, some, every 其实都可以用来遍历?

所以总的来说学习一个新知识比较好的方式是先脚踏实地的把基础弄懂,然后就是多用,用的过程中多思考,多中结。

数组实现栈和队列

虽然 Javascript 这门语言没有提供标准的数据结构类,但是其实到处都有数据结构的影子,对象其实本身就是 Map,对象还可以看做 Tree,队列和栈其实都可以用数组来实现,它们的区别只是行为上不一样而已。push,pop 可以用来实现栈:

const stack = [];

stack.push('a');
stack.push('b');

// 符合栈后进先出的特点
console.log(stack.pop()); // => b
console.log(stack.pop()); // => a

 

实现队列其实也很简单,使用 push 和 shift 即可:

const queue = [];

queue.push('a');
queue.push('b');

// 符合队列先进先出的特点
console.log(queue.shift()); // => a
console.log(queue.shift()); // => b

 

splice

const testArray = ['c', 'd', 'd'];
// 删除操作,第一个参数表示删除的起始下标, 第二个参数表示删除的个数
testArray.splice(1, 1);

// 第三个参数及其往后表示插入的元素,可以结合结构赋值使用
const ab = ['a', 'b'];
testArray.splice(0, 0, ...ab);
console.log(testArray); // => [ 'a', 'b', 'c', 'd' ] 

 

其实 Javascript 这门语言本身可以说早期是设计的非常糟糕了,你没有单独的 remove 和 insert 方法就算了,唯一一个可以用来插入删除的 API 还设计的这么反直觉。正常人的思维肯定是希望返回一个新数组,而不是修改原数组,假设设计者是基于性能考虑才不返回一个修改后的新数组,那么为何又要返回一个保存了删除了元素的数组。我如果需要删除的那几个元素我直接 slice 不好吗?返回一个数组很容易让人误解这是返回修改后新数组。

reverse

const arr = [1, 2, 3];
console.log(arr.reverse()); // => [ 3, 2, 1 ]
console.log(arr); // => [ 3, 2, 1 ]
// 居然返回原数组!!!
console.log(arr.reverse() === arr); // => true

 

reverse 和 splice 一样都被设计成有副作用的不纯函数。问题是为嘛要返回一个新数组,容易让人误解返回的是新数组,我觉得压根就不用返回新数组,你返回 undefined 那就等于告诉使用者这里是修改原数组,多好啊。

slice

有些人可能不知道 slice 其实是可以接受负数的:

const arr = ['a', 'b', 'c', 'd'];
console.log(arr.slice(-3)); // => [ 'b', 'c', 'd' ]  截取从最后一个数组下标开始
console.log(arr.slice(-3, -1)); // => [ 'b', 'c' ]

 

查找元素

查找元素的方法有很多,indexOf/lastIndexOf/includes/find/findIndex。经常看到有人写类似下面这样的代码:

const arr = ['a', 'b', 'c', 'd'];

const isExists = arr.indexOf('k') != -1;
if (isExists) {
  console.log('数组中存在 k');
}

 

如果你要判断数组中是否包含某个元素,明显 ES7 引入的 includes 函数更合适,可读性好多了。

const handleSelect = newValue => {
  if (this.state.includes(newValue)) {
    message.error(`您已经选择过${newValue},不能重复选择!`);
  }
};

 

lastIndexOf 在一些需要反向查找的情况下还是很有用的。其实 includes 叫查找元素还不太准确,find 才是真正的查找元素,find 返回的是元素本身,所以当你需要在数组中查找元素并且返回这个元素的时候你可以考虑使用 find。有 indexOf 不够吗为什么还有个 findIndex 呢?确实不够,有些场景下,使用函数式的高阶函数可以大大提高接口的灵活性。

const students = [{ Chinese: 120, English: 138 }, { Chinese: 140, English: 110 }, { Chinese: 108, English: 120 }];
const chineseHighest = students.find(stu => stu.Chinese === 140);
console.log(chineseHighest); // => { Chinese: 140, English: 110 } 

f

 

上面这个查找语文分数为 140 的学生用 indexOf 是不可能做的,使用高阶函数,让使用者传递一个函数去完成接口中的关键步骤这样的方式来扩展接口灵活性在 Javascript 到处可见,像 findIndex,sort 都是这样,所以我之前在面美团的时候被问到说函数式有什么用啊,这不就是吗?提高接口的灵活性。

至于啥时候用 findIndex, 那肯定是当你需要被查找元素的下标而不是元素本身喽。

join

数组的 join 方法其实挺常用的,来举几个案例:

获取重复的字符串

console.log(`${Array(35).fill('*').join('')} 我是美丽的分割线 ${Array(35).fill('*').join('')}`);
// => *********************************** 我是美丽的分割线 *********************************** 

 

将数组中的内容拼接成字符串

let url = 'http://xxx.com/xxx';

const params = {
  name: 'lyreal666',
  age: 21,
};

const query = [];
Object.keys(params).forEach(key => {
  query.push(`${key}=${params[key]}`);
});
url += `?${query.join('&')}`;

console.log(url);

 

我的同事写过类似上面的代码,其实有很多可以吐槽的地方。上面的代码目的是为了得到一个 queryString,其实最开始的数据时个对象,为什么最后就能将对象的内容拼接成字符串呢?这其实你要这样想:不要把对象只是当成一个对象,对象是可以转换成数组的,所以对象也可以其实也可以充分利用数组的那些接口,包括这里的 join。

其实我平时转换 queryString 我是使用标准对象 URLSearchParams

new URLSearchParams({ name: 'ly', age: 21 }).toString(); // => "name=ly&age=21"

 

一行代码解决,不使用标准对象也可以优雅的实现,其实可以 join 都不用,后面会提到。

sort

sort 这里补充一个坑:js 数组的 sort 默认是按照元素的字符串码值排序。当需要对数字数字排序需要自定义比较函数。

const arr = [111, 11, 8, 2, 7, 4, 3];
console.log(arr.sort()); // => [ 11, 2, 3, 4, 7, 8 ]
console.log(arr.sort((x, y) => x - y)); // => [ 2, 3, 4, 7, 8, 11 ]

 

flat

flat 是 ES2019 的语法,用于数组的扁平化,可以使用 reduce 和 concat 偏平到最里层的 flat。思路是这样的:

你要得到一个最终的结果 result 数组,你必须遍历每一个元素将其合并到结果数组,又考虑到遍历到的元素可能本身也是个数组,那就将其先扁平化再合并,也就是使用递归,扁平化数组元素后返回的是一个数组。哪个 API 可以将一个数组并将其合并到 result 数组呢?自然是 concat。那遍历收集每个数组元素得到一个和初始值类型相同的情况选择那个接口呢,当然是 reduce,一步到位就是下面的代码:

const flat = array => array.reduce((pre, current) => pre.concat(Array.isArray(current) ? flat(current) : current), []);

const testArray = [1, [2, [3, 4], 5, [6, 7], 8], 9];
console.log(flat(testArray)); // => [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

 

forEach/filter/map/reduce/reduceRight/some/every

reduceRight 和 reduce 只是遍历的方向不同,所以后面不会单独讲 reduceRight。

forEach 和 for 循环有什么区别?

  1. forEach 提前退出循环,而 for 循环可以,直接 break 就可以。
  2. 当 forEach 接受的函数是 async 没法 await 的,也就是说每次执行的 async 函数之间是并发的,而 for 循环可以使用 await 让每次执行的 async 函数之间是同步的
  3. forEach 是函数式风格而 for 循环是命令式风格

关于上面第二点,我举个例子:

const sleep = seconds =>
  new Promise(resolve => {
    setTimeout(() => resolve(), seconds * 1000);
  });

const crawl = async url => {
  console.log(`start crawl url: ${url}...`);
  await sleep(3);
  console.log(`crawl url: ${url} end...`);
};

const urls = ['http://a.com', 'http://b.com', 'http://c.com', 'http://d.com', 'http://e.com'];
// forEach
console.time('Test forEach');
urls.forEach(crawl);
console.timeEnd('Test forEach');

// for loop
(async function testForLoop() {
  console.time('Test for loop');
  for (const url of urls) await crawl(url);
  console.timeEnd('Test for loop');
})();


// =>
// start crawl url: http://a.com...
// start crawl url: http://b.com...
// start crawl url: http://c.com...
// start crawl url: http://d.com...
// start crawl url: http://e.com...
// Test forEach: 2.837ms
// start crawl url: http://a.com...
// crawl url: http://a.com end...
// crawl url: http://b.com end...
// crawl url: http://c.com end...
// crawl url: http://d.com end...
// crawl url: http://e.com end...
// crawl url: http://a.com end...
// start crawl url: http://b.com...
// crawl url: http://b.com end...
// start crawl url: http://c.com...
// crawl url: http://c.com end...
// start crawl url: http://d.com...
// crawl url: http://d.com end...
// start crawl url: http://e.com...
// crawl url: http://e.com end...
// Test for loop: 15012.782ms

 

上面列举的那些高阶函数之间有什么区别?

都可以用来遍历,区别在于返回值和用途不同。

  1. forEach 无返回值,常用于存粹的遍历,大多数情况可以替代 for 循环使用
  2. filter 返回原数组的子集,用于对原数组的进行过滤筛选
  3. map 返回的和原数组长度相同的映射数组,用于映射到另外一个数组
  4. reduce/reduceRight 返回一个和初始值类型相同的值,中文叫归并操作,用于遍历数组每个元素收集需要的数据返回一个值
  5. some/every 返回值都是 boolean 类型。只有 some 和 every 可以提前退出遍历,用于判断数组中有元素满足或者所有元素是否满足某条件。

filter/map 返回的都是新数组,并不会修改原数组,除非你在遍历过程中修改了原数组的元素,非常不建议在遍历操作中修改原数组,除非你清楚的知道修改的后果是什么。

什么时候用 forEach 什么时候用 Map?

当然是看你需不需要返回值啦,forEach 就是纯粹的遍历,Map 是用来映射原数组的。

reduce 有什么用?

来看几个案例:

还是上面那个获取 queryString 的,我用 reduce 来改写一下,思考过程是这样的:我最终要得到一个字符串,这个字符串是遍历所有的元素得到的,显然不能用 map,map 是返回数组, reduce 可以啊,reduce 是扫描一遍每一个元素合成一个值啊。

let url = 'http://xxx.com/xxx';

const params = {
  name: 'lyreal666',
  age: 21,
};

// 使用 map 来实现
// url += '?' + Object.entries(params).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&');

// 使用 reduce
url += Object.entries(params).reduce(
  (pre, [key, value]) => `${pre}${pre === '?' ? '' : '&'}${encodeURIComponent(key)}=${encodeURIComponent(value)}`,
  '?'
);
console.log(url); // => http://xxx.com/xxx?name=lyreal666&age=21

 

连乘或连加

const add = (...operands) => operands.reduce((pre, current) => pre + current, 0);
console.log(add(2, 3, 3)); // => 8

const pow = (x, y = 2) => Array.from({ length: y }).reduce(pre => pre * x, 1);
console.log(pow(3)); // => 9
console.log(pow(2, 3)); // => 8

 

再来看看 redux 中的 compose

const compose = (...funcs) => {
  if (funcs.length === 0) {
    return args => args;
  }

  if (funcs.length === 1) {
    return funcs[0];
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)));
};

const a = arg => {
  console.log(`call a, arg: ${arg}`);
};

const b = arg => {
  console.log(`call b, arg: ${arg}`);
  return 'a';
};
const c = arg => {
  console.log(`call c, arg: ${arg}`);
  return 'b';
};

const composedFunc = compose(
  a
  b,
  c
);

// 即执行效果为 arrgs => a(b(c(args)))
composedFunc('c');

// => 
// call c, arg: c
// call b, arg: b
// call a, arg: a

 

所以 reduce 使用的时候一般就是当你需要通过遍历一个数组计算出一个值得时候。

some/every 该怎么用?

这俩和短路或,短路与很像。当你需要判断数组中的是否有一个或多个元素满足条件时考虑使用 some,只要一个元素满足就会退出遍历。当你需要判断数组中的元素是都都满足某个条件时使用 every,只要有一个元素不满足就会退出。

some 和 every其实是可以相互转换的,你想啊,数组中有一个或多个瞒住条件 condition 是不是数组中所有元素都满足 !condition 的结果取反。

看一个例子:

// 小明的分数
const grades = [80, 59, 80];

// 完蛋,要被老爸打屁屁
const isOver = grades.some((grade) => grade < 60);
// 等同于
// const isOver = !grades.every((grade) => grade >= 60);

 

链式调用

在使用这几个高阶函数的时候我们经常是链式调用的,例如:

// level 为 0 表示管理员
const users = [
  { name: 'ly', level: 2 },
  { name: 'Bob', level: 1 },
  { name: 'Lily', level: 0 },
  { name: 'Tom', level: 3 },
];

const customerNames = users
  .filter(user => user.level !== 0)
  .map(customer => customer.name)
  .join(', ');

console.log(customerNames); // => ly, Bob, Tom

 

比起 for 循环不但节省代码,逻辑还更清晰,而且因为处理过程是分步的,出错的时候我们只需要关注出错的那步调用,如果是 for 循环的话代码往往是糅杂在一起的,分析起来涉及面比较广。看看 for 循环版本的:

// level 为 0 表示管理员
const users = [
  { name: 'ly', level: 2 },
  { name: 'Bob', level: 1 },
  { name: 'Lily', level: 0 },
  { name: 'Tom', level: 3 },
];

let str = '';
for (const user of users) {
  if (user.level !== 0) {
    str += `${str === '' ? '' : ', '}${user.name}`;
  }
}
console.log(str); // => ly, Bob, Tom

 

This article summarizes some considered me the voice of experience and Javascript array of possible follow-up will add some content. I hope to give readers some inspiration, especially since some learning I mentioned, hoping for some beginners can play some guidance.

If the content of the article there is nothing wrong or inappropriate, please point out in the comments area. Thanks for reading, if the article for your help or inspiration, one might point Like, look at the pictures.

This article is original content, starting in a personal blog , please indicate the source.

 

Guess you like

Origin www.cnblogs.com/tommymarc/p/11627933.html