一. 高阶函数和回调函数
高阶函数: function(fn) 括号里面有函数类型的参数 或者 返回的值是一个函数
//
function every(fn){
fn(); //当一个函数执行的时候,它的参数是一个函数,执行时或者执行后,这个函数又执行了, 这个函数就是原函数的回调函数
//所以回调函数属于高阶函数?
}
//
回调函数: 把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,这就叫做回调。如果代码立即被执行就称为同步回调,如果在之后晚点的某个时间再执行,则称之为异步回调。
疑问
回调函数属于高阶函数范畴?
二. every: 判断数组元素有无
1.every也是原型链上的方法:Array.prototype.every
2.every()语句中,如果有一个不满足条件就停止遍历,条件就是return后面的表达式
var data = [{'name':'0', 'age':'18'}, {'name':'1', 'age':'28'}, {'name':'2', 'age':'28'} ]
var res = data.every(function(elem, index, arr){
console.log(elem); // 仅输出 {'name':'0', 'age':'18'}, {'name':'1', 'age':'28'}
// 因为到第二个就return false了
return elem.name == '0'
console.log(elem); //不会输出, 他会一步步遍历,到return 就戛然而止,不管return后面表达式是否正确,如果正确就遍历下一句,如果不正确就直接结束遍历,
//所以说不管return的表达式正确与否,其后面的所有语句都不会执行,正确了就再次遍历,不正确就结束遍历
})
所以说不管return的表达式正确与否,其后面的所有语句都不会执行,正确了就再次遍历,不正确就结束遍历
-
every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
var data = [{ 'name': '0', 'age': '18' }, { 'name': '1', 'age': '28' }, { 'name': '2', 'age': '28' }] var res = data.every(function (elem, index, arr) { // 因为到第二个就return false了 return elem.name == '0' }) console.log(res); //输出false
every的重写
Array.prototype.myEvery = function (fn) {
var arr = this, //data中的数据
len = arr.length,
args2 = arguments[1] || window,
res = true;
for (var i = 0; i < len; i++) {
if (!fn.apply(args2, [arr[i], i, arr])) {
res = false;
break;
}
}
return res;
}
var data = [ { name: '1', age: '28' }, { name: '2', age: '28' }];
var res2 = data.myEvery(function (elem, index, array) {
console.log(elem);
return elem.name == '1' //判断data的数据, 如果==0 只会输出data的第一项, ==1输出两项 ,因为判断语句在log之后,总会输出一句
}, { name: 'jack' })
//所以说every()括号内配合 return elem.xx == 'xx' 使用
//return比较的是data中的值,那此句中argus2有什么用?
所以说every()括号内配合 return elem.xx == 'xx' 使用,比较data中的数据
但是argus2的作用是什么? 知道特性就好,以后箭头函数等会有用
三. some
其功能和every差不多,也是判断数组有无此元素
唯一的区别就是: 如果有一个满足条件就停止遍历,条件是return后面的表达式
通俗的讲: some 遇到正确的就停止, 遇到不正确的就一直循环下去,直至找到正确的
而every 第一项不是正确的就会停止遍历,第一项正确就会继续遍历
some重写
Array.prototype.mySome = function (fn) {
var arr = this, //data中的数据
len = arr.length,
args2 = arguments[1] || window,
res = false;
for (var i = 0; i < len; i++) {
if (fn.apply(args2, [arr[i], i, arr])) {
res = true;
break;
}
}
return res;
}
var data = [ { name: '1', age: '28' }, { name: '2', age: '28' }, { name: '23', age: '28' }];
var res2 = data.mySome(function (elem, index, array) {
console.log(elem);
return elem.name == '0' //输出{ name: '1', age: '28' }, { name: '2', age: '28' }, { name: '23', age: '28' }
}, { name: 'jack' })
//遇到正确的就停止,遇到不正确的就一直循环下去,直至找到正确的
四. reduce: 完成数据归纳
返回一个新的数组,把符合条件的值放入新数组中
reduce的第二个参数必须填
var data = [ { name: '1', age: '28' }, { name: '2', age: '28' }, { name: '23', age: '28' }];
var initialValue = [];
var nArr = data.reduce(function(prev, elem, index, arr){ //将prev与其他三项分开来看
console.log(prev === initialValue);// 返回true,所以prev和initialValue是一个东西
return prev; //必须return prev; 才会有值, 不然会输出3次undefined (次数为数组中元素的个数,即遍历的次数)
}, initialValue)
1.prev和initialValue是一个东西, prev的值从initialValue中获取, 所以第二个参数必须填
2.必须return才会有值,不然之后的返回会几次false(次数为数组中元素的个数 - 1,因为第一次返回true)
var data = [{ name: '1', age: '28' }, { name: '2', age: '28' }, { name: '23', age: '28' }];
var initialValue = [];
var nArr = data.reduce(function (prev, elem, index, arr) { //将prev与其他三项分开来看
prev.push(elem.name); // 每执行data.reduce 的时候都会操作一遍prev.push();
console.log(prev); //输出["1"] 、 ["1", "2"]、 ["1", "2", "23"]
return prev;
}, initialValue)
每执行data.reduce 的时候 都会操作一遍prev.push();
reduce的本质其实也是遍历, 会执行一次次里面的语句
var data = [{ name: '1', age: '28' }, { name: '2', age: '28' }, { name: '23', age: '28' }];
var initialValue = [];
var nArr = data.reduce(function (prev, elem, index, arr) { //将prev与其他三项分开来看
if(elem.name === '1'){
prev.push(elem);
}
return prev; //返回给新数组nArr
}, initialValue)
console.log(nArr); //输出{name: "1", age: "28"}
所以说reduce 和 filter 的作用是一样的,但是方法不同: reduce是用归纳的方式来做的,而filter是过滤
过滤: 返回布尔值是true就返回, 不是就扔掉
归纳: 在我的条件范围之内,往一个新容器里面放值(并不是原来的那个容器) 即将符合条件的全部放入新的容器中
var data = [{ name: '1', age: '28' }, { name: '2', age: '28' }, { name: '23', age: '28' }];
var initialValue = [];
var nArr = data.reduceRight(function (prev, elem, index, arr) { //将prev与其他三项分开来看
prev.push(elem);
// console.log(elem);
return prev;
}, initialValue)
console.log(nArr); //输出: {name: "23", age: "28"} 、{name: "2", age: "28"}、{name: "1", age: "28"}
所以说reduceRight 和 reduce 唯一的不同就是返回结果是倒着来的 reduceRight就是倒序列
总结
所有的数组拓展方法本质都是 遍历、循环
reduce是从0开始遍历,reduceRight是从 长度(data.length-1) 开始遍历
reduce 实战
将cookie数据的" name= 1; name2= 2 ; name3= 23 " 形式改为对象的形式
var cookieData = " name= 1; name2= 2 ; name3= 23 "
cookieArr = cookieData.split(";");
// console.log(cookieArr); //数组,输出 [ name= 1", " name2= 2 ", " name3= 23 " ]
var nArr = cookieArr.reduce(function(prev, elem){
var item = elem.split('=');
console.log(item); //返回三个数组
// [" name", " 1"] [" name2", " 2 "] [" name3", " 23 "]
prev [item[0]] = item[1];
return prev;
}, {}) //因为prev为空对象,所以nArr返回一个对象
console.log(nArr);
//输出{" name": " 1", " name2": " 2 ", " name3": " 23 "}
reduce一次次遍历,把他们分隔开:[" name", " 1"] [" name2", " 2 "] [" name3", " 23 "]
同时 prev [item[0]] = item[1]: 因为prev为一个对象,它把数组的第0项变为了键名,第一项变为键值,
所以才会呈现 name : 1 的形式
reduce的重写
Array.prototype.myReduce = function (fn, init) {
var arr = this,
len = arr.length,
args2 = arguments[2] || window; //对应init的下标
for (var i = 0; i < len; i++) {
init = fn.apply(args2, [init, arr[i], i, arr]);
}
return init;
}
var cookieData = " name= 1; name2= 2 ; name3= 23 "
cookieArr = cookieData.split(";");
var nArr = cookieArr.myReduce(function (prev, elem) {
var item = elem.split('=');
// console.log(item); //返回三个数组
prev[item[0]] = item[1];
return prev;
}, {})
console.log(nArr);
以上输出{" name": " 1", " name2": " 2 ", " name3": " 23 "}
1. args2 = arguments[2] || window; 是因为上面的参数有两个:第二个参数是init, 第三个参数才是{}
2. init = fn.apply(args2, [init, arr[i], i, arr]); 将 function 中返回的值 全部放入第二个参数 { } 中, 返回第二个参数
reduceRight重写
唯一的不同就是for循环里面
for (var i = len - 1; i >= 0; i--) {
init = fn.apply(args2, [init, arr[i], i, arr]);
}
return init;
}
五. 难点
elem是调用数组中的元素,和this指向无关,所以不可能是第二个参数的数组元素, 此问题困扰了很久,最近才整明白
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!