重写数组的方法(二)

84 阅读3分钟

前言

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

自我学习,模拟数组的方法:

数组方法.png

需要借助深拷贝函数

function deepClone(origin, target) {
    var tar = target || {}

    for (var k in origin) {
        if (origin.hasOwnProperty(k)) {
            if (typeof origin[k] === 'object' && origin[k] !== null) {
                tar[k] = Object.prototype.toString.call(origin[k]) === '[Object Array]' ? [] : {}
                deepClone(origin[k], tar[k])
            } else {
                tar[k] = origin[k]
            }
        }
    }
    return tar
}

不改变原数组的方法:

filter

检测数组元素,并返回符合条件所有元素的数组。


const arr = [{ name: '程卓', age: 21, 'Chinese': 90, 'Math': 95 }, { name: 'Nick', age: 22, 'Chinese': 80, 'Math': 85 }]
const obj = { name: 'cc', age: 18, }


Array.prototype.myFilter = function(fn) {
   var _arr = this //保存this指向, Array调用,指向arr
   var _length = _arr.length //保存arguments的长度
   // var _argOptionThis = arguments[1] || globalThis // forEach的第二个参数,可选  node环境
   var _argOptionThis = arguments[1] || window // forEach的第二个参数,可选  浏览器环境
   var _newArr = []
   var _item
   for (var i = 0; i < _length; i++) {
      _item = deepClone(_arr[i])
      fn.apply(_argOptionThis, [_item, i, _arr]) ? _newArr.push(_item) : ''
   }
   return _newArr
}

var arrFilter = arr.filter(function(item, index, arr) {
   return item.age > 21
}, obj)

console.log(arrFilter)

var arrMyFilter = arr.myFilter(function(item, index, arr) {
   return item.age > 21
}, obj)

console.log('arrMyFilter:',arrMyFilter)

重写filter.png

join

把数组中的所有元素放入一个字符串。

Array.prototype.myJoin = function (separator) {
	if (this.length == 0) {
		return "";
	}
	if (separator == undefined) {
		separator = ",";
	}
	var str = "" + this[0];
	for (var i = 1; i < this.length; i++) {
		str = str + separator + this[i];
	}
	return str;
}

concat

拼接数组,不改变原数组。

Array.prototype.myConcat = function () {
	var arr2 = [];
	for (var i = 0; i < this.length; i++) {
		arr2[i] = this[i];
	}
	for (var i = 0; i < arguments.length; i++) {
		if (Array.isArray(arguments[i])) {
			for (var j = 0; j < arguments[i].length; j++) {
				arr2.myPush(arguments[i][j]);
			}
		} else {
			arr2.myPush(arguments[i]);
		}
	}
	return arr2;
}

map

map会返回一个新数组。

var newArr = arr.map(function (item, index, array) {
   console.log(item, index)
   return item
}, obj)

console.log(newArr)


const arr = [{name: '程卓', 'Chinese': 90, 'Math': 95}, {name: 'Nick', 'Chinese': 80, 'Math': 85}]
const obj = {name: 'cc'}


Array.prototype.myMap = function (fn) {
   var _arr = this                           //保存this指向, Array调用,指向arr
   var _length = _arr.length;                   //保存arguments的长度
   var _argOptionThis = arguments[1] || globalThis          // forEach的第二个参数,可选  node环境
   // var _argOptionThis = arguments[1] || window          // forEach的第二个参数,可选
   var _newArr = []


   for(var i = 0; i < _length; i++) {
      deepClone(arr[i])
      _newArr.push(fn.apply(_argOptionThis, [arr[i], i , _arr]))
   }
   return _newArr
}


重写map.png

forEach

对数组中的每一元素运行给定的函数,常用来遍历元素,没有返回值,但回调函数可以改变数组,。


arr.forEach(function(item, index, arr) {
    console.log(item, index, arr)
})
const arr = [
    { name: '程卓', age: 21, 'Chinese': 90, 'Math': 95 },
    { name: 'Nick', age: 22, 'Chinese': 80, 'Math': 85 }
]
const obj = { name: 'cc', age: 23, }

Array.prototype.myForEach = function(fn) {
    var _arr = this                        //保存this指向, Array调用,指向arr
    var _length = _arr.length;             //保存arguments的长度
    
    // var _argOptionThis = arguments[1] || globalThis             // forEach的第二个参数,可选  node环境
    
    var _argOptionThis = arguments[1] || window             // forEach的第二个参数,可选  浏览器环境
    for (var i = 0; i < _length; i++) {
                                                    //不知道是否传入第二个参数,需要绑定this指向,
                                                    //apply方法,里面的第二个参数是数组(item, index, arr)
        fn.apply(_argOptionThis, [_arr[i], i, _arr]) 
    }
}

arr.myForEach(function(item, index, arr) {
    console.log(item, index, arr)
}.obj)
简单点
Array.prototype.myForEach = function (callback) {
    for (var i = 0; i < this.length; i++) {
        var element = this[i];
        callback(element, i, this);
    }
}


重写forEach.png

every

对数组中的每一运行给定的函数,如果该函数对每一项都返回true,则该函数返回true。

Array.prototype.MyEvery = function(fn) {
   for (var i = 0; i < this.length; i++) {
      var item = this[i]
      if(!fn(item, i, this)) { 
         return false  //函数失败返回false
      }
   }
   return true
}

some

对数组中的每一运行给定的函数,如果该函数对任一项都返回true,则返回true。

Array.prototype.mySome = function (fn) {
   for (var i = 0; i < this.length; i++) {
      var item = this[i];
      if (fn(item, i, this)) {
         return true; //任意一个函数执行成功返回 true
      }
   }
   return false;
}

reduce

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

Array.prototype.myReduce = function (fn, initValue) {
   var num = 0;
   var sum;
   if (initValue !== undefined) {
      sum = initValue;
   } else {
      sum = this[0];
      num = 1;
   }
   for (var  i = num; i < this.length; i++) {
      var item = this[i];
      sum = fn(sum, item, i, this);
   }
   return sum;
}

indexOf

从数组开头向后查找,使用全等操作符,找不到该元素返回-1。第一个参数为要查找的项,第二个参数(可选)为索引开始位置。

Array.prototype.myIndexOf = function (item, start) {
	var index = -1;
	if (start == undefined) {
		start = 0;
	}
	for (var i = start; i < this.length; i++) {
		if (this[i] == item) {
			index = i
			return index;
		}
	}
	return index;
}