29 数组相关
1 实现forEach方法
Array.prototype.myForEach = function(callback, context=window) {
// this=>arr
let self = this,
i = 0,
len = self.length;
for(;i<len;i++) {
typeof callback == 'function' && callback.call(context,self[i], i)
}
}
2 实现filter方法
Array.prototype.myFilter=function(callback, context=window){
let len = this.length
newArr = [],
i=0
for(; i < len; i++){
if(callback.apply(context, [this[i], i , this])){
newArr.push(this[i]);
}
}
return newArr;
}
3 实现find方法
find接收一个方法作为参数,方法内部返回一个条件find会遍历所有的元素,执行你给定的带有条件返回值的函数- 符合该条件的元素会作为
find方法的返回值 - 如果遍历结束还没有符合该条件的元素,则返回
undefined
var users = [
{id: 1, name: '张三'},
{id: 2, name: '张三'},
{id: 3, name: '张三'},
{id: 4, name: '张三'}
]
Array.prototype.myFind = function (callback) {
// var callback = function (item, index) { return item.id === 4 }
for (var i = 0; i < this.length; i++) {
if (callback(this[i], i)) {
return this[i]
}
}
}
var ret = users.myFind(function (item, index) {
return item.id === 2
})
console.log(ret)
4 实现findIndex方法
var users = [
{id: 1, name: '张三'},
{id: 2, name: '张三'},
{id: 3, name: '张三'},
{id: 4, name: '张三'}
]
Array.prototype.myFindIndex = function (callback) {
// var callback = function (item, index) { return item.id === 4 }
for (var i = 0; i < this.length; i++) {
if (callback(this[i], i)) {
// 这里返回
return i
}
}
}
var ret = users.myFind(function (item, index) {
return item.id === 2
})
console.log(ret)
5 实现map方法
- 回调函数的参数有哪些,返回值如何处理
- 不修改原来的数组
Array.prototype.myMap = function(callback, context){
// 转换类数组
var arr = Array.prototype.slice.call(this),//由于是ES5所以就不用...展开符了
mappedArr = [],
i = 0;
for (; i < arr.length; i++ ){
// 把当前值、索引、当前数组返回去。调用的时候传到函数参数中 [1,2,3,4].map((curr,index,arr))
mappedArr.push(callback.call(context, arr[i], i, this));
}
return mappedArr;
}
6 实现reduce方法
- 初始值不传怎么处理
- 回调函数的参数有哪些,返回值如何处理。
Array.prototype.myReduce = function(fn, initialValue) {
var arr = Array.prototype.slice.call(this);
var res, startIndex;
res = initialValue ? initialValue : arr[0]; // 不传默认取数组第一项
startIndex = initialValue ? 0 : 1;
for(var i = startIndex; i < arr.length; i++) {
// 把初始值、当前值、索引、当前数组返回去。调用的时候传到函数参数中 [1,2,3,4].reduce((initVal,curr,index,arr))
res = fn.call(null, res, arr[i], i, this);
}
return res;
}
7 实现every方法
Array.prototype.myEvery=function(callback, context = window){
var len=this.length,
flag=true,
i = 0;
for(;i < len; i++){
if(!callback.apply(context,[this[i], i , this])){
flag=false;
break;
}
}
return flag;
}
// var obj = {num: 1}
// var aa=arr.myEvery(function(v,index,arr){
// return v.num>=12;
// },obj)
// console.log(aa)
8 实现some方法
Array.prototype.mySome=function(callback, context = window){
var len = this.length,
flag=false,
i = 0;
for(;i < len; i++){
if(callback.apply(context, [this[i], i , this])){
flag=true;
break;
}
}
return flag;
}
// var flag=arr.mySome((v,index,arr)=>v.num>=10,obj)
// console.log(flag);
9 实现数组扁平化flat方法
题目描述: 实现一个方法使多维数组变成一维数组
let ary = [1, [2, [3, [4, 5]]], 6];
let str = JSON.stringify(ary);
第0种处理:直接的调用
arr_flat = arr.flat(Infinity);
第一种处理
ary = str.replace(/(\[|\])/g, '').split(',');
第二种处理
str = str.replace(/(\[\]))/g, '');
str = '[' + str + ']';
ary = JSON.parse(str);
第三种处理:递归处理
let result = [];
let fn = function(arr) {
for(let i = 0; i < arr.length; i++) {
let item = arr[i];
if (Array.isArray(arr[i])){
fn(item);
} else {
result.push(item);
}
}
}
第四种处理:用 reduce 实现数组的 flat 方法
function flatten(ary) {
return ary.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flatten(cur) : cur);
}, []);
}
let ary = [1, 2, [3, 4], [5, [6, 7]]]
console.log(flatten(ary))
第五种处理:能用迭代的思路去实现
function flatten(arr) {
if (!arr.length) return;
while (arr.some((item) => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
// console.log(flatten([1, 2, [1, [2, 3, [4, 5, [6]]]]]));
第六种处理:扩展运算符
while (ary.some(Array.isArray)) {
ary = [].concat(...ary);
}
10 实现Array.isArray方法
Array.myIsArray = function(o) {
// 调用顶级对象上的toString方法转成[object Array]形式
return Object.prototype.toString.call(o) === '[object Array]';
};
console.log(Array.myIsArray([])); // true
11 实现Array.of方法
Array.of()方法用于将一组值,转换为数组
- 这个方法的主要目的,是弥补数组构造函数
Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。 Array.of()基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
实现
function ArrayOf(){
return [].slice.call(arguments);
}
12 数组去重方法汇总
首先:我知道多少种去重方式
1. 双层 for 循环
function distinct(arr) {
for (let i=0, len=arr.length; i<len; i++) {
for (let j=i+1; j<len; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
// splice 会改变数组长度,所以要将数组长度 len 和下标 j 减一
len--;
j--;
}
}
}
return arr;
}
思想: 双重
for循环是比较笨拙的方法,它实现的原理很简单:先定义一个包含原始数组第一个元素的数组,然后遍历原始数组,将原始数组中的每个元素与新数组中的每个元素进行比对,如果不重复则添加到新数组中,最后返回新数组;因为它的时间复杂度是O(n^2),如果数组长度很大,效率会很低
2. Array.filter() 加 indexOf/includes
function distinct(a, b) {
let arr = a.concat(b);
return arr.filter((item, index)=> {
//return arr.indexOf(item) === index
return arr.includes(item)
})
}
思想: 利用
indexOf检测元素在数组中第一次出现的位置是否和元素现在的位置相等,如果不等则说明该元素是重复元素
3. ES6 中的 Set 去重
function distinct(array) {
return Array.from(new Set(array));
}
思想: ES6 提供了新的数据结构 Set,Set 结构的一个特性就是成员值都是唯一的,没有重复的值。
4. reduce 实现对象数组去重复
var resources = [
{ name: "张三", age: "18" },
{ name: "张三", age: "19" },
{ name: "张三", age: "20" },
{ name: "李四", age: "19" },
{ name: "王五", age: "20" },
{ name: "赵六", age: "21" }
]
var temp = {};
resources = resources.reduce((prev, curv) => {
// 如果临时对象中有这个名字,什么都不做
if (temp[curv.name]) {
}else {
// 如果临时对象没有就把这个名字加进去,同时把当前的这个对象加入到prev中
temp[curv.name] = true;
prev.push(curv);
}
return prev
}, []);
console.log("结果", resources);
这种方法是利用高阶函数
reduce进行去重, 这里只需要注意initialValue得放一个空数组[],不然没法push
13 对象数组如何去重
根据每个对象的某一个具体属性来进行去重
const responseList = [
{ id: 1, a: 1 },
{ id: 2, a: 2 },
{ id: 3, a: 3 },
{ id: 1, a: 4 },
];
const result = responseList.reduce((acc, cur) => {
const ids = acc.map(item => item.id);
return ids.includes(cur.id) ? acc : [...acc, cur];
}, []);
console.log(result); // -> [ { id: 1, a: 1}, {id: 2, a: 2}, {id: 3, a: 3} ]
14 数组中的数据根据key去重
给定一个任意数组,实现一个通用函数,让数组中的数据根据 key 排重:
const dedup = (data, getKey = () => {} ) => {
// todo
}
let data = [
{ id: 1, v: 1 },
{ id: 2, v: 2 },
{ id: 1, v: 1 },
];
// 以 id 作为排重 key,执行函数得到结果
// data = [
// { id: 1, v: 1 },
// { id: 2, v: 2 },
// ];
实现
const dedup = (data, getKey = () => { }) => {
const dateMap = data.reduce((pre, cur) => {
const key = getKey(cur)
if (!pre[key]) {
pre[key] = cur
}
return pre
}, {})
return Object.values(dateMap)
}
使用
let data = [
{ id: 1, v: 1 },
{ id: 2, v: 2 },
{ id: 1, v: 1 },
];
console.log(dedup(data, (item) => item.id))
// 以 id 作为排重 key,执行函数得到结果
// data = [
// { id: 1, v: 1 },
// { id: 2, v: 2 },
// ];
15 类数组转化为数组的方法
const arrayLike=document.querySelectorAll('div')
// 1.扩展运算符
[...arrayLike]
// 2.Array.from
Array.from(arrayLike)
// 3.Array.prototype.slice
Array.prototype.slice.call(arrayLike)
// 4.Array.apply
Array.apply(null, arrayLike)
// 5.Array.prototype.concat
Array.prototype.concat.apply([], arrayLike)
16 reduce用法汇总
语法
array.reduce(function(total, currentValue, currentIndex, arr), initialValue);
/*
total: 必需。初始值, 或者计算结束后的返回值。
currentValue: 必需。当前元素。
currentIndex: 可选。当前元素的索引;
arr: 可选。当前元素所属的数组对象。
initialValue: 可选。传递给函数的初始值,相当于total的初始值。
*/
reduceRight()该方法用法与reduce()其实是相同的,只是遍历的顺序相反,它是从数组的最后一项开始,向前遍历到第一项
1. 数组求和
const arr = [12, 34, 23];
const sum = arr.reduce((total, num) => total + num);
// 设定初始值求和
const arr = [12, 34, 23];
const sum = arr.reduce((total, num) => total + num, 10); // 以10为初始值求和
// 对象数组求和
var result = [
{ subject: 'math', score: 88 },
{ subject: 'chinese', score: 95 },
{ subject: 'english', score: 80 }
];
const sum = result.reduce((accumulator, cur) => accumulator + cur.score, 0);
const sum = result.reduce((accumulator, cur) => accumulator + cur.score, -10); // 总分扣除10分
2. 数组最大值
const a = [23,123,342,12];
const max = a.reduce((pre,next)=>pre>cur?pre:cur,0); // 342
3. 数组转对象
var streams = [{name: '技术', id: 1}, {name: '设计', id: 2}];
var obj = streams.reduce((accumulator, cur) => {accumulator[cur.id] = cur; return accumulator;}, {});
4. 扁平一个二维数组
var arr = [[1, 2, 8], [3, 4, 9], [5, 6, 10]];
var res = arr.reduce((x, y) => x.concat(y), []);
5. 数组去重
实现的基本原理如下:
① 初始化一个空数组
② 将需要去重处理的数组中的第1项在初始化数组中查找,如果找不到(空数组中肯定找不到),就将该项添加到初始化数组中
③ 将需要去重处理的数组中的第2项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中
④ ……
⑤ 将需要去重处理的数组中的第n项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中
⑥ 将这个初始化数组返回
var newArr = arr.reduce(function (prev, cur) {
prev.indexOf(cur) === -1 && prev.push(cur);
return prev;
},[]);
6. 对象数组去重
const dedup = (data, getKey = () => { }) => {
const dateMap = data.reduce((pre, cur) => {
const key = getKey(cur)
if (!pre[key]) {
pre[key] = cur
}
return pre
}, {})
return Object.values(dateMap)
}
7. 求字符串中字母出现的次数
const str = 'sfhjasfjgfasjuwqrqadqeiqsajsdaiwqdaklldflas-cmxzmnha';
const res = str.split('').reduce((pre,next)=>{
pre[next] ? pre[next]++ : pre[next] = 1
return pre
},{})
// 结果
-: 1
a: 8
c: 1
d: 4
e: 1
f: 4
g: 1
h: 2
i: 2
j: 4
k: 1
l: 3
m: 2
n: 1
q: 5
r: 1
s: 6
u: 1
w: 2
x: 1
z: 1
8. compose函数
redux compose源码实现
function compose(...funs) {
if (funs.length === 0) {
return arg => arg;
}
if (funs.length === 1) {
return funs[0];
}
return funs.reduce((a, b) => (...arg) => a(b(...arg)))
}
