数组的手写方法

107 阅读1分钟

这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

JS中有很多实用的内置方法,尝试自己去实现相同功能的方法有助于我们加强我们对这些方法的理解,以达到更好的使用这些方法的目的,同时手写方法也是面试中常常考察的点。

map

语法:

var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg])

thisArg执行 callback 函数时值被用作this

Array.prototype.fakeMap = function(fn,context ) {
	let result = []
  for(let i = 0;i<this.length;i++){
    if(!this.hasOwnProperty(i)) continue; // 处理稀疏数组的情况
		result.push(fn.call(context,this[i],i,this))  	
  }
  return result 
}


var arr = [1,2,3]
var arrSum = arr.fakeMap(item => item+2)
console.log(arrSum)

// 验证this,使用箭头函数,this指向windows对象
var obj1 = {a:3}
var arr1 = [1,2,3]
var arrSum1 = arr1.fakeMap((item) => {
  console.log(this.a)
 return this.a+item
},obj1)
console.log(arrSum1)

// 验证 this,this指向obj3
var arr3 = ["x", "y", "z"];
var obj3 = { a: 1 };
var result3 = arr3.fakeMap(function(item) {
  console.log(this.a);
  return item + this.a
}, obj3);
console.log(result3)

filter

语法

var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])

Array.prototype.fakeFilter = function(fn,context){
	let result = []
  for(let i=0; i<this.length; i++){
  	if(!this.hasOwnProperty(i)) continue;
    if(fn.call(context,this[i],i,this)){
    	result.push(this[i])
    }
  }
  return result
}

var arr = [1,2,3]
var obj = {a:2}
console.log(arr.fakeFilter(item => item>1))
// 验证this
console.log(arr.fakeFilter(function(item){
  return item>this.a
},obj))

reduce

语法

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

Array.prototype.fakeReduce = function(fn,initialValue){
	//let result = initialValue||this[0]
  // 处理初始值为0的情况
  
  let result = typeof(initialValue)==='undefined'?this[0]:initialValue
  console.log(initialValue,result)
  
  for(let i= typeof(initialValue)!=='undefined'?0:1;i<this.length;i++){
    if(!this.hasOwnProperty(i)) continue; // 处理稀疏数组的情况
  	let currentValue = this[i]
    console.log("currentValue",currentValue)
    result = fn(result,currentValue,i,this)
    console.log("result",result)
  }
  return result
}

var arr = [1,2,3]
var result = arr.fakeReduce(function(x,y){
	return x+y
})
console.log(result) // 6

// 验证初始值
var result1 = arr.fakeReduce(function(x,y){
	return x+y
},10)
console.log(result1) // 16

应用

累加对象中的值,必须提供初始值。

var initalValue = 0
var sum = [{x: 1}, {x:2}, {x:3}].fakeReduce(function (accumulator, currentValue) {
    return accumulator + currentValue.x;
},initalValue)

console.log(sum)

every

every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值

语法

arr.every(callback(element[, index[, array]])[, thisArg])

Array.prototype.fakeEvery = function(fn,context){
	let flag = true;
  for(let i=0;i<this.length;i++){
    if(!this.hasOwnProperty(i)) continue; // 处理稀疏数组的情况
  	flag = flag&&fn.call(context,this[i],i,this)
    if(!flag) break
  }
  return flag
}
var arr = []
var flag = arr.fakeEvery(function(item){
	return item<3
})
console.log(flag)

// 验证this
var arr1 = [1,2,3]
var obj = {a:3}
var flag1 = arr1.fakeEvery(function(item){
	return item<this.a
},obj)
console.log(flag1)

some

some() 方法测试一个数组内是否至少有一个元素满足回调函数的测试。返回一个布尔值。

语法

arr.some(callback(element[, index[, array]])[, thisArg])

Array.prototype.fakeSome = function(fn,context){
	let flag = false;
  for(let i=0;i<this.length;i++){
    if(!this.hasOwnProperty(i)) continue; // 处理稀疏数组的情况
  	flag = fn.call(context,this[i],i,this)
    if(flag) break
  }
  return flag
}


var arr = [1,3,4]
var flag = arr.fakeSome(function(item){
	return item<3
})
console.log(flag)

// 验证this
var arr1 = [1,2,3]
var obj = {a:3}
var flag1 = arr1.fakeSome(function(item){
	return item<this.a
},obj)
console.log(flag1)

find

find()方法返回数组中第一个通过测试函数的值,没有返回undefined

语法:

arr.find(callback[, thisArg])

callback:

element

index

array

Array.prototype.fakeFind = function(fn,context){
	let result = undefined
  for(let i=0;i<this.length;i++){
    if(!this.hasOwnProperty(i)) continue; // 处理稀疏数组的情况
  	if(fn.call(context,this[i],i,this)){
    	result = this[i]
      break
    }
  }
  return result
}

//测试
;(function() {
  let arr = [1,2,3]
  let obj = {a:3}

  let result = arr.fakeFind((item) => item>1)
  let result2 = arr.fakeFind((item) =>{
      console.log(this) // ? 这个this没传过来
      return item>this.a
  },obj)
  console.log(result,result2)
})();

flat

数组扁平化

reduce

const flatten = function(arr){
  if(!Array.isArray(arr)) return;
	let result = []
  result = arr.reduce((res,curr) => res.concat(Array.isArray(curr)?flatten(curr):curr),[])
  return result
}

;(function(){
 	let arr = [1,2,[3,4]]
	console.log(flatten(arr))
 })()

堆栈

const flatten = function(arr){
  if(!Array.isArray(arr)) return;
  let stack = [...arr]
	let result = []
  while(stack.length){
  	let value = stack.shift()
    if(Array.isArray(value)){
    	stack.push(...value)
    }else{
    	result.push(value)
    }
  }
  return result
}


	let arr = [1,2,[3,4,[5,6]]]
	console.log(flatten(arr))