es6常用的方法及其原理-大杂烩【持续更新】

10 篇文章 0 订阅

一、 reduce 与 reduceRight

1、reduce 将一个数组中的一系列值计算出一个值(从左往右算)

//result 表示所有计算结束后返回的值,也就是最后一次return的值
let result = arr.reduce(function(val,item,index,origin){
    //val当前值,
    //item当前元素,
    //index当前索引,
    //origin老数组

return 表达式; //每次return的值都会成为新的val

},initval);
//initval代表初始值

//注意,如果有initval,则会将这个初始值先赋值给第一次的val;如果没有,val就是第一个元素,item就是第二个元素,也就是会少循环一次;同样,没有初始值,那么index就从1开始,而不是从0开始

举例——求和:

let arr = [1,2,3];
arr.reduce(function(val,item,index,origin){
    return val + item;
},0)

举例——求平均值

let arr = [1,2,3];
arr.reduce(function(val,item,index,origin){
    let sum = val + item;
    if(index === origin.length - 1){
        return sum/origin.length;
   }else{
        return sum;
   }
},0)

1.1、用es5实现reduce方法【原理

Array.prototype.reduce = function(reduceFn,initVal){
    if(typeof reduceFn !== 'function'){
        throw new Error(`${reduceFn} is not a function`);
        return;
    }
    var initIndex;
    if(typeof initVal === 'undefined'){
        initVal = this[0];
        initIndex = 1;
    }else{
        initIndex = 0;
    }
    for(var i = initIndex;i < this.length; i++){
        initVal = reduceFn(initVal,this[i],i,this);
    }
    return initVal;
}

//举例:求和
let arr = [1,2,3];
let result;
result = arr.reduce(function(val,item,index,origin){
    return val + item;
},0);
console.log(result);//6

2、reduceRight与reduce类似,唯一不同的是前者从右往左计算,后者从左往右计算。

举例——求平均数

let arr = [1,2,3];let resulet = arr.reduce(function(val,item,index,origin){
    let sum = val + item;
    if(index === 0){
        return sum/origin.length;
    }else{
        return sum;
    }
},0)

2.1、用es5实现reduceRight方法

Array.prototype.reduceRight = function(reduceFn,initVal){
    if(typeof reduceFn !== 'function'){
        throw new Error(`${reduceFn} is not a function`);
        return;
    }
    var initIndex;
    if(typeof initVal === 'undefined'){
        initVal = this[this.length - 1];
        initIndex = this.length - 2;
    }else{
        initIndex = this.length - 1;
    }
    for(var i = initIndex;i >= 0; i--){
        initVal = reduceFn(initVal,this[i],i,this);
    }
    return initVal;
}

3、origin

origin指的是原数组,那么当我们存在原数组跟新数组的时候,必须要关注一个问题——两者之间是引用关系还是简单的值拷贝关系?
很简答,当我们去改变origin的值的时候,去打印原数组,如果原数组也改变,那么就说明引用关系,反之则为值拷贝关系。

let arr = [1,2,3];
let result = arr.reduceRight(function(val,item,index,origin){
    origin[index] = origin[index]+'zhuangzhuang';
},0)
console.log(arr);//['1zhuangzhuang','2zhuangzhuang','3zhuangzhuang'];

上面的例子,可见是引用关系。
在回到上面看原理,其实我们并没有去处理origin,而是直接引用,所以原理中也是引用关系

二、filter

filter这个方法,用于对数组的过滤

let arr = [1,2,3,4,5];
let newArr = arr.filter(function(item,index,origin){
    return 布尔值;
},thisArg)
/*
    filter有两个参数:
        1.callback
            callback有三个参数
                a.item 数组中正在处理的元素
                b.index 数组中正在处理的元素的索引值
                c.被调用数组,即arr,这跟reduce的origin一样,是引用关系
        2.thisArg
            用于改变callback中的this指向

*/
//return true,把此元素保留在数组中
//return false,把此元素不保留在数组中
//newArr 范围值为新元素,该方法不修改原来的数组

举例一:

let arr = [1,2,3,4,5,6];
let newArr = arr.filter(function(item,index){
    return item > 3;
})
console.log(newArr);//[4,5,6]

这样,就直接过滤出大于3的每项元素了,组成一个新数组
那么,用es5怎么来实现呢?
真的极其简单:

/*
    用es5解释es6中filter的原理
*/

Array.prototype.filter = function(filterFn,thisArg){
    let newArr = [];
    for(var i = 0;i<_this.length;i++){
        let _this = this.slice(0);//注意,务必要先复制一份
        filterFn.call(thisArg,_this[i],i,this) && newArr.push(_this[i]);
    }
    return newArr;
}

let arr = [1,2,3,4,5,6];
let newArr = arr.filter(function(item,index,origin){
    console.log(this);//'zhuangzhuang'
    return item > 3;
},'zhuangzhuang')
console.log(newArr,arr);//[4,5,6]

需要注意一点
当我们去改变origin的时候,并不能改变item,因为item是origin的副本中的项
如果thisArg不传,在非严格模式下将会是全局对象,严格模式下是 undefined。
关于filter,有专门写一篇文章,详细请查看>>传送门<<

三、find

该方法主要用于查找数组元素

let arr = [1,2,3,4];
let result = arr.find(function(item,index,origin){
    return item % 2 === 0;
},'zhuangzhuang')
console.log(result);//2

可见,其实他找到的是满足return后面为true的第一个元素。一旦找到,就不再往后面查找。
原理跟filter一样简单:

/*
    用es5解释es6中find的原理
*/

Array.prototype.find = function(filterFn,thisArg){
    let newArr = [];
    for(var i = 0;i<_this.length;i++){
        let _this = this.slice(0);
        if(filterFn.call(thisArg,_this[i],i,this)){
            return _this[i];
        }
    }
}

let arr = [1,2,3,4,5,6];
let newArr = arr.find(function(item,index,origin){
    return item % 2 === 0;
},'zhuangzhuang')
console.log(newArr,arr);//2 (6) [2, 3, 3, 4, 5, 6]

跟filter一样,需要注意一点
当我们去改变origin的时候,并不能改变item,因为item是origin的副本中的项
如果thisArg不传,在非严格模式下将会是全局对象,严格模式下是 undefined。

四、findIndex

跟上面的find一样,唯一的区别是上面的find返回元素,这个findIndex返回的是索引

let arr = [1,2,3,4];
let result = arr.findIndex(function(item,index){
    return item % 2 === 0;
})
console.log(result);//1

原理:

Array.prototype.findIndex = function(filterFn,thisArg){
    let newArr = [];
    for(var i = 0;i<_this.length;i++){
        let _this = this.slice(0);
        if(filterFn.call(thisArg,_this[i],i,this)){
            return i;
        }
    }
}

let arr = [1,2,3,4,5,6];
let newArr = arr.findIndex(function(item,index,origin){
    return item % 2 === 0;
},'zhuangzhuang')
console.log(newArr,arr);

跟filter一样,需要注意一点
当我们去改变origin的时候,并不能改变item,因为item是origin的副本中的项
如果thisArg不传,在非严格模式下将会是全局对象,严格模式下是 undefined。

五、some and every

与上面的不同的是,some和every返回的是布尔值
some:存在满足条件的 即返回true,否则返回false
every:所有元素都满足条件 即返回true,否则返回false

let arr = [1,2,3,4];
let bool = arr.some(function(item,index,origin){
    return item > 1;
},null)
console.log(bool);//true,存在元素大于1的
let arr = [1,2,3,4];
let bool = arr.every(function(item,index,origin){
    return item > 1;
},null)
console.log(bool);//false,有一个没有大于1

原理同上,非常简单,就不写了
如果thisArg不传,在非严格模式下将会是全局对象,严格模式下是 undefined。

六、将类数组转成数组(2种方法)

类数组:具有length属性,但不具有数组方法的数据格式,比如DOM、arguments等,具体可以看这篇文章:>>传送门<<
那么,类数组如何转变成数组,在这里介绍两种方法:

方法一:通过将Array的this指向类数组
let arr = Array.prototype.slice.call(类数组);
>arr即为数组
>在这里,如果你想让类数组遍历,使用数组forEach方法,可以直接如下:
Array.prototype.forEach.call(类数组,function(item,index,origin){

})
方法二:ES6方法
let arr = Array.from(类数组);
>arr即为数组

七、创建数组的方法

方法一:let arr = [];
方法二:Array.of
Array.of(3);//[3]
Array.of(3,4);//[3.4]
方法三:Array()
Array(3);//[empty × 3]长度为3,但是没有元素
Array(3,4);//[3,4]
方法四:new Array()
new Array(3);//[empty × 3]长度为3,但是没有元素
new Array(3,4);//[3,4]

(以下正在写…)

浅拷贝与深拷贝

1、浅拷贝与深拷贝的区别
2、如何实现深拷贝

方法一:转字符串再转回来
方法二:递归(要考虑object包含null、Array、function、object)

未完待续

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值