继上一篇 Array.prototype.reduce 后,我立志要好好学习。琢磨了好久,再加上最近看了几篇"JS 函数式编程"的文章和书籍后,而后有感而发写下了这篇文章。编程
Array.prototype.map
方法相信你们都用的很熟悉了,同时我也相信不少人已经本身实现了 map
函数。没有实现过本身的map
? 不要紧,咱们先用for
循环来实现下。数组
Array.prototype.selfMap = function () {
const ary = this
const result = new Array(ary.length);
const [ fn, thisArg ] = [].slice.call(arguments)
if (typeof fn !== 'function') {
throw new TypeError(fn + 'is not a function')
}
for (let i = 0; i < ary.length; i++) {
// fix稀疏数组的状况
if (i in ary) {
result[i] = fn.call(thisArg, ary[i], i, ary);
}
}
return result
}
const a = new Array(1, 2, 3, 4)
a.selfMap(item => item + 1) // [ 2, 3, 4, 5 ]
复制代码
实现了本身的map
,还不是美滋滋。app
可是,这和本文没有半点关系,由于我是要用reduce
实现map
啊🤣🤣🤣函数式编程
众所周知,map
函数须要传一个函数的,还有一个可选的this
参数,可是我发现第二个参数你们不多用到,也不怎么注意,我也是这样。函数
[1, 2, 3].map(function(item) {
console.log(this)
return item
}, { msg: 'mapping' })
复制代码
上面👆这段代码块不只会返回一个新的数组,还会在控制台打印三次post
{ msg: 'mapping' }
复制代码
有图有真相👇学习
可能有的小伙伴在验证我上面的例子时,会使用箭头函数
,而后发现老是打印window
,就是下面这样👇ui
而后内心暗道“无耻小儿,竟敢骗我”。内心苦啊,箭头函数在声明时就绑定了它外层的this(此例的this
为window
,并且还改变不了, 也就是说{ msg: 'mapping' }
至关于白传了)😭this
彷佛废话有点多额,那咱们先用reduce
来实现map
吧(默认运行环境支持Array.prototype.reduce
,若是不支持的话,那还写个🔨)spa
// 此次不把方法写在Array的原型上
const reduceMap = (fn, thisArg /*真想去掉thisArg这个参数*/ ) => {
return (list) => {
// 不怎么愿意写下面这两个判断条件
if (typeof fn !== 'function') {
throw new TypeError(fn + 'is not a function');
}
if (!Array.isArray(list)) {
throw new TypeError('list must be a Array');
}
if (list.length === 0) return [];
const result = new Array(list.length);
return list.reduce((acc, value, index) => {
// fix稀疏数组的状况
if (index in list) {
acc[index] = fn.call(thisArg, value, index, list);
}
return acc;
}, result);
}
}
// 来使用下怎么样🧐
reduceMap(x => x + 1)([ 1, 2, 3 ]) // [ 2, 3, 4 ]
const mapAry1 = reduceMap(function(item) {
console.log(this)
return item + 1
}, { msg: 'mapping' })([ 1, 2, 3 ])
// [ 2, 3, 4 ]
// logging { msg: 'mapping' } three times
复制代码
👆实现的原理相信你们应该都懂吧。
打铁当趁热,继续来实现filter
吧。
Array.prototype.selfFilter = function () {
const ary = this
const result = []
const [ fn , thisArg ] = [].slice.call(arguments)
if (typeof fn !== 'function') {
throw new TypeError(fn + 'is not a function')
}
const result = [];
for (let i = 0; i < ary.length; i++) {
if (i in ary && fn.call(thisArg, ary[i], i, ary)) {
result.push(ary[i])
}
}
return result
}
const a = new Array(1, 2, 3)
a.selfFilter(item => item % 2 === 0) // [ 2 ]
a.selfFilter(function (item) {
console.log(this)
return item % 2 === 0
}, {})
// [ 2 ]
// logging {} three times
复制代码
// 同map, 不定义在Array的原型上
const reduceFilter = (fn, thisAry /* thisAry知不知你好讨厌啊 */ ) => {
return (list) => {
if (typeof fn !== 'function') {
throw new TypeError(fn + 'is not a function')
}
if (!Array.isArray(list)) {
throw new TypeError('list must be a Array')
}
if (list.length === 0) return []
return list.reduce((acc, value, index) => {
return index in ary && fn.call(thisAry, value, index, list) ? acc.concat([ value ]) : acc
}, [])
}
}
reduceFilter(x => x % 2 === 0)([ 1, 2, 3 ]) // [ 2 ]
复制代码
文章里掺杂了些许函数式编程里面的东西,由于我也才开始学函数式编程不久,就不在大佬们面前献丑了。若是文章里有哪里写的不对或者不够准确,亦或者是以为有写的很差的地方,烦请各位指正,也让我改正。