原生JS数组方法(一)ES5数组方法的描述及原理实现

js数组方法

原生数组方法的描述

数组方法 参数描述 函数原理简述 原数组变化 返回值
push (需要插入的元素) 添加一个或多个元素到数组的末尾 改变 操作后的数组长度
pop 删除一个数组中的最后一个元素 改变 被删除的元素
shift 删除数组的第一个元素,并返回这个元素 改变 被删除的元素
unshift (需要插入的值) 在数组的开头插入一个或多个元素 改变 数组长度
reverse 前后颠倒数组中元素的位置,第一个元素会成为最后一个 改变 操作后数组
sort (空/比较函数) 对数组的元素做原地的排序,并返回这个数组。sort可能不稳定,默认按照字符串的unicode码位点排序 改变 操作后的原数组
splice (开始索引,要删除数量,要插入值) 在任意的位置给数组添加或删除任意个元素(拼接);拼接,拆分数组 改变 被删除的值(数组形式)无则为空数组
copyWithin (开始索引,替代数组开始的索引/空[默认为0],替代数组结束的索引/空[默认为数组长度]) 用于在数组内的替换操作,即替换元素和被替换元素都是数组内的元素 改变 操作后的原数组
concat (需要拼接的数组) 用于合并两个或多个数组 不变 操作后的数组
includes (值,索引/查询起始位置) 用来判断当前数组是否包含某指定的值 不变 布尔值
indexOf (值,索引/查询起始位置) 返回在数组中可以找到一个给定元素的第一个索引 不变 索引
lastIndexOf (值,索引/查询起始位置) 返回在数组中可以找到一个给定元素的最后一个索引,会从数组的后面向前查找 不变 索引
join (连接符) 将一个数组(或一个类数组对象)的所有元素连接成一个字符串 不变 连接后的字符串
slice (开始索引,终止索引/不包含该位置) 在任意的位置给数组添加或删除任意个元素(拼接) 不变 按逻辑增删后的数组(不改变原数组)
toString 使数组变成字符串,用’,’连接。若数组的值存在数组,会便遍历拼接在字符串里;对象,会变成[object Object];undefined则什么都不连接,即会变成, 不变 字符串
toLocalString 使数组变成字符串,用’,’连接。数组内的元素会调用自己的toLocalString方法 不变 字符串
forEach (callback(item/值,index/索引,array/原数组),v/callback执行的作用域) ) forEach遍历的范围在第一次调用 callback前就会确定。调用forEach后添加到数组中的项不会被 callback访问到。如果已经存在的值被改变,则传递给 callback的值是 forEach遍历到他们那一刻的值。已删除的项不会被遍历到 不变
map (callback(item/值,index/索引,array/原数组),v/callback执行的作用域)) 一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组 不变 返回值构成的新数组
keys 返回一个新的Array迭代器,它包含数组中每个索引的键 不变 Array迭代器
values 返回一个新的Array迭代器,它包含数组中每个值的键 不变 Array迭代器
entries 返回一个新的Array迭代器,它包含数组中每个键值对[index,item] 不变 Array迭代器
every (callback(value,key,arr),v/callback执行的作用域)) 若数组的值执行callback全部返回true,则最终返回true 不变 布尔值
some (callback(value,key,arr),v/callback执行的作用域)) 若数组的值执行callback有一个返回true,则最终返回true 不变 布尔值
filter (callback(value,key,arr),v/callback执行的作用域)) 使用指定的函数测试所有元素,并创建一个包含所有测试通过的元素的新数组 不变 使callback返回true的值组成的数组
find ((callback(v,k,a),v/callback执行的作用域) ) 返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。 不变 通过测试的第一个元素值或undefined
findIndex ((callback(v,k,a),v/callback执行的作用域) ) 返回数组中满足提供的测试函数的第一个元素的值的索引。否则返回 undefined。 不变 通过测试的第一个元素值的索引或undefined
reduce (callback(p/上一次回调的返回值,v/当前被处理的元素,i/索引,a/原数组)=> {},initialValue初始值) 该方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值 不变 最后的返回值
reduceRight (callback(p/上一次回调的返回值,v/当前被处理的元素,i/索引,a/原数组) ,initialValue初始值) 该方法接收一个函数作为累加器(accumulator),数组中的每个值(从右到左)开始合并,最终为一个值 不变 最后的返回值
Array.from (类数组对象) 一个类似数组或可迭代对象中创建一个新的数组实例 不变 数组实例
Array.isArray (需要检测的元素) 判断一个元素是否为数组 不变 布尔值
Array.isArray (元素–可多个) 创建一个具有可变数量参数的新数组实例 不变 数组实例
fill (value,开始索引,结束索引) 将数组中指定区间的所有元素的值,都替换成value 改变

1、ES5数组方法

push()可以接受多个参数,并将这些参数放置于数组尾部,返回新数组的长度,原始数组发生改变。

Array.prototype.myPush =function(){
for (var i = 0; i < arguments.length; i++) {
//arguments代表实参的集合
//this 指向的是arr数组
this[this.length] = arguments[i];
}
//由于push 返回值 是一个数组的长度 所以 我们来个return;
return this.length;
};

arr.push(4,5,6);
alert(arr);
//-----结果 [1,2,3,4,5,6];

pop()不接收参数,从数组尾部删除一个元素,并返回这个删除的元素,原数组发生改变。

  Array.prototype.myPop = function( ){
            var len=this.length;
            var result = this[len-1];
            this.length = len - 1;
            return result;
        }
        var a = [1,2,3,4]
        console.log(a.myPop( ))//-----结果4;
        console.log(a);//-----结果 [1,2,3];

unshift()接受多个参数并,将这些参数放置于数组头部,返回新数组的长度,原数组发生改变。

  Array.prototype.myUnshift=function( ){
    var len=arguments.length-1;
    this.length=this.length+len;
    for(var i=this.length-1;i>=0;i--){
        this[i+len]=this[i]
    }
    for(var j=1;j<arguments.length;j++){
            this[j-1]=arguments[j]
        }
    return this.length
}
var arr=[1,2,5,6];
arr.unshift(10,11)//6
console.log(arr)//[10,11,1,2,5,6];

shift()不接受参数,从数组的头部删除一个元素,并返回这个删除的元素,原数组发生改变。

 Array.prototype.myShift = function(){
      var result = this[0]
      for(var i=0;i<this.length-1;i++){
        this[i] = this[i+1]
      }
      this.length = this.length-1
      return result;
   }
    var a = [1,2,3,4]
     a.myShift()//1
     console.log(a)//[2,3,4]

slice()如果是一个参数,那么该参数表示的索引开始截取,直至数组结束,返回截取的数组,原数组不发生改变。
如果有两个参数,从第一个参数表示的索引开始截取,到第二个参数表示的索引结束,不包括第二个参数对应的索引位上的元素。

Array.prototype.mySlice = function () {
    var startIndex = Number(arguments[0]), 
   endIndex = Number(arguments[1]), 
    newArr = [];
   endIndex =endIndex === undefined ? this.length : Number(endIndex) ? Number(endIndex) : 0;
   endIndex =endIndex < 0 ? Math.abs(endIndex) > this.length &&endIndex > -1? 0 : 
   this.length + Math.ceil(endIndex) :endIndex > this.length ? this.length : Math.floor(endIndex);
    startIndex = startIndex ? startIndex < 0 ? Math.abs(startIndex) > this.length || startIndex > -1 
    ? 0 : this.length + Math.ceil(startIndex) : startIndex > this.length ? this.length: Math.floor(startIndex) : 0;
    for (var i = startIndex; i <endIndex; i++) {
        newArr[newArr.length] = this[i];
    }
    return newArr;
};
var arr=[1,2,3,4,5];
var a1=arr.mySlice(1,3);
console.log(Array.prototype.slice.call({ 0:'a', 1:'b', length:2 }))// ["a", "b"]
console.log(a1)//[2, 3],

注; slice方法的一个重要应用,是将类似数组的对象转为真正的数组。

Array.prototype.slice.call({ 0'a'1'b', length:2 }) /// ['a', 'b']
Array.prototype.slice.call(document.querySelectorAll("div"));
Array.prototype.slice.call(arguments)

上面代码的参数都不是数组,但是通过call方法,在它们上面调用slice方法,就可以把它们转为真正的数组。

		var arr=[123456]var arr1=arr.slice(13)var arr1=arr.slice(  )//如果没有任何参数就会从头截取到尾部 拷贝
        var arr1=arr.slice(1)//如果第二个参数没有,就会从开始截取到尾部
        var arr1=arr.slice(-3-1)//如果是负数就会从后向前数,然后再截取
		//前小于后将参数转换为正向数值时,前面的必须小于后面
        var arr1=arr.slice(-35)//如果第一个参数大于等于数组长度,或者第二个参数小于第一个参数,则返回空数组。
        console.log(arr1,arr)

splice() 如果一个参数,那么从该参数表示的索引开始截取,直至数组结束,返回截取的数组,原数组发生改变。
如果有两个参数,从第一个参数表示索引,第二个参数表示的是截取的长度。
如果有三个及以上参数,从第一个参数表示索引,第二个参数表示的是截取的长度,后边的会从截取的位置添加至原数组里。

  1. splice方法用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。
arr.splice(start, count, addElement1, addElement2, ...)
  1. splice的第一个参数是删除的起始位置(从0开始也包含该元素),第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。
var a = ['a''b''c''d''e''f'];
a.splice(42) ////["e", "f"]
a //// ["a", "b", "c", "d"]

上面代码从原数组4号位置,删除了两个数组成员。

var a = ['a''b''c''d''e''f'];
a.splice(4212) // ["e", "f"]
a // ["a", "b", "c", "d", 1, 2]

上面代码除了删除成员,还插入了两个新成员。
3. 起始位置如果是负数,就表示从倒数位置开始删除

var a = ['a''b''c''d''e''f'];
a.splice(-42) //// ["c", "d"]

上面代码表示,从倒数第四个位置c开始删除两个成员。
4. 添加元素;如果只是单纯地插入元素,splice方法的第二个参数可以设为0。

var a = [111];
a.splice(102) //// [ ]
a //// [1, 2, 1, 1]

5.如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组。

var a = [1234];
a.splice(2) //// [3, 4]
a // //[1, 2]

原理实现:

 Array.prototype.mySplice = function () {
    var _arr = [],//操作的原数组
        len = this.length,//数组长度
        startIndex = arguments[0],//第一个参数:起始索引
        deleteNum = arguments[1],//第二个参数:删除长度
        insertNum = arguments.length - 2,//添加元素数量
        leftArr = [],//删除元素左边数组
        rightArr = [];//删除元素右边数组
    if (startIndex < 0 || deleteNum < 0) {
        return _arr;
    }
    // 删除
    for (var i = 0; i < deleteNum; i++) {
        _arr[i] = this[startIndex + i]
        for (var i = 0; i < len - deleteNum - startIndex; i++) {
            this[startIndex + i] = this[startIndex + deleteNum + i]
        }
        this.length = len - deleteNum
        if (insertNum === 0) {
            return _arr
        }
    }
    // 添加;替换
    for (var i = 0; i < len - deleteNum; i++) {
        if (i < startIndex) {
            leftArr[leftArr.length] = this[i]
        } else {
            rightArr[rightArr.length] = this[i]
        }
    }
    rightArr.length = len - startIndex - deleteNum;
    for (var i = 0; i < insertNum; i++) {
        leftArr[startIndex + i] = arguments[i + 2];
    }
    for (var i = 0; i < len - deleteNum + insertNum; i++) {
        if (i < startIndex + insertNum) {
            this[i] = leftArr[i]
        } else {
            this[i] = rightArr[i - startIndex - insertNum]
        }
    }
    return _arr;
}
var a = ['a', 'b', 'c', 'd', 'e', 'f',undefined];
a.splice(4, 2) 

// var a = ['a', 'b', 'c', 'd', 'e', 'f'];
// a.splice(4, 2, 1, 2) 

// var a = ['a', 'b', 'c', 'd', 'e', 'f'];
// a.splice(-4, 2) 

// var a = [1, 1, 1];
// a.splice(1, 0, 2);

// var a = [1, 2, 3, 4];
// a.splice(2) 
console.log(a)

reverse()数组翻转参数无意义;改变数组;并返回操作后的原数组。

Array.prototype.myReverse = function( ){
    var arr = this;
    var len=parseInt(arr.length/2)
    for(var i=0;i<len;i++){
        var temp=arr[arr.length-1-i]
        arr[arr.length-1-i]=arr[i];
        arr[i]=temp
    }
    return arr//改变数组
}
var arr=[1,2,4,5,6,7,7,4,3,5]
arr.myReverse( )
console.log(arr)//[5, 3, 4, 7, 7, 6, 5, 4, 2, 1]

sort()对数组的元素做原地的排序,并返回这个数组。sort可能不稳定,默认按照字符串的unicode码位点排序。改变数组;并返回操作后的原数组。

var arr = [2,11,50,7,9];
console.log(arr.sort());//按照字符串按位比较方式来判断大小的
arr.sort(function(a,b){
	return a - b;//从小到大
	return b-a;//从大到小
})
console.log(arr);
[101111101111].sort(function (a, b) {return a - b;})
// [111, 1101, 10111]
[4321].sort(  ) // [1, 2, 3, 4]
[11101].sort(  )   ///[101, 11]
[
  { name:"张三", age:30 }{ name:"李四", age:24 }{ name:"王五", age:28  }]
.sort(function (o1, o2) {
  	return o1.age - o2.age;})
// [
//   { name:"李四", age:24 },
//   { name:"王五", age:28  },
//   { name:"张三", age:30 }]

原理实现:

Array.prototype.mySort = function(fn){
    if(Object.prototype.toString.call(fn)==='[object Function]'){
        //如果传进来参数的是函数
        for(var i = 0;i<this.length-1;i++){
            //遍历数组,将前后两项作为实参传给fn
            if(fn.call(this,this[i],this[i+1])>0){
                //如果fn执行之后的返回值大于0.就调用swap方法交换位置
                var a = this[i],b=this[i+1];
                this[i] = swap(a,b).a;
                this[i+1] = swap(a,b).b;
                //交换之后,如果当前项不是第一项,则当前项(索引为i的项)继续跟前面的项进行比较
                if(i>0){
                    for(var j = i-1;j>=0;j--){
                            if(fn.call(this,this[j],this[j+1])>0){
                                var a = this[j],b=this[j+1];
                                this[j] = swap(a,b).a;
                                this[j+1] = swap(a,b).b;
                            }
                        }
                }
            }
        }
    }else{
        //如果不是函数,则按正常排序
        //遍历数组,将前后两项进行比较
        for(var i = 0;i<this.length-1;i++){
            var cur = this[i];//当前项
            var next = this[i+1];//下一项
            if(comASCII(cur,next)){
                //当返回true的时候交换,并且交换完成之后,当前项继续往前比较
                this[i] = swap(cur,next).a;
                this[i+1] = swap(cur,next).b;
                //当前项继续向前比较
                if(i>0){
                    for(var k = i-1;k>=0;k--){
                        var cur = this[k];
                        var next = this[k+1];
                        if(comASCII(cur,next)){
                            this[k] = swap(cur,next).a;
                            this[k+1] = swap(cur,next).b;
                        }
                    }
                }
            }
        }
    }
    //封装一个交换位置的函数
    function swap(a,b){
        return {
            a:b,
            b:a
        }
    }
    //如果不传参的情况下比较ASCII码
    function comASCII(cur,next){
        //全部转换为字符串、逐项比较ASCII码
        cur = cur.toString();
        next = next.toString();
        //取长度最大值
        var len = cur.length>next.length?next.length:cur.length;
        //当前后两项都不是不是{}类型的数据时,进行比较
        if(cur!=='[object Object]'&&next!=='[object Object]'){
            for(var j = 0;j<len;j++){
                if(!isNaN(cur.charCodeAt(j))&&!isNaN(next.charCodeAt(j))){
                    //如果二者的ASCII码都是有效数字
                    if(cur.charCodeAt(j)>next.charCodeAt(j)){
                        //如果前一项比后一项当前的ASCII码大,则返回true,交换位置
                        return true;
                    }else if(cur.charCodeAt(j)==next.charCodeAt(j)){
                    //如果相等直接进入下一轮循环
                            continue;
                        }else{
                        //前项比后项小,直接返回false
                            return false;
                        }
                }
            }
            if(!isNaN(cur.charCodeAt(len))&&isNaN(next.charCodeAt(len))&&(cur.charCodeAt(len-1)==next.charCodeAt(len-1))){
                //比较完之后,如果前一项ASCII还是有效数字,说明前项比后项大,交换
                return true;
            }
        }
        //如果上述条件不满足,则不交换
        return false;
    }
    //返回当前数组
    return this;
};

说到排序就不得不说三种经典的排序方式:

1. 冒泡排序

 //原理:数组中有n个数,比较相邻的两个数,如果后面的数小于前面的数,则两者交换。
//一轮完成后,此时最大的数据已经在最后,此时进行第二轮,确定倒数第二个数,依次几轮就可完成:
    //1、从后向前循环
    //2、内部从前向后循环到外层变量
    //3、判断前面的值是否大于后面的值,交换
    Array.prototype.Mpsort=function(){
        var arr=this;
        var len=arr.length;
        while(len>0){
            for(var i=0;i<len;i++){
                if(arr[i]>arr[i+1]){
                    var temp=arr[i];
                    arr[i]=arr[i+1];
                    arr[i+1]=temp;
                }
            }
            len--;
        }
    }
    var arr=[1,2,4,6,3,2,6,8]
    arr.Mpsort();
    console.log(arr);

2. 快速排序

 //原理:取数组中间位置的数据,跟所有数据比较,比该数小的放一新数组,大的放一新数组,使用递归,拼接数据,最后得到想要的数组
//重新赋值给元素替换
Array.prototype.quickSort = function ( ) {
    var arr=this
    if (arr.length <= 1) { return arr; }
    var item = arr.splice(parseInt(arr.length / 2), 1)[0];
    // var item = arr.splice(Math.floor(arr.length / 2), 1)[0];
    var leftArr = [];
    var rightArr = [];
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] < item) {
          leftArr.push(arr[i]);
        } else {
            rightArr.push(arr[i]);
        }
    }
    return leftArr.quickSort().concat([item], rightArr.quickSort());
};

var arr = [1, 2, 34, 2, 1, 3, 2, 8]
arr=arr.quickSort();
console.log(arr)

3. 选择排序

  //选择排序;
    //先找出最小或者最大的索引值,然后用当前的下标的元素与这个最小的元素比较
    Array.prototype.mySort=function(){
        var minIndex;
        var arr=this;
        for(var i=0;i<arr.length;i++){
            minIndex=i;
            for(var j=i+1;j<arr.length;j++){
                minIndex=arr[minIndex]<arr[j]?minIndex:j;
            }
            var temp=arr[i];
            arr[i]=arr[minIndex];
            arr[minIndex]=temp;
        }
    }
    var arr=[1,2,4,5,6,32,2,2];
    arr.mySort();
    console.log(arr)

join()将数组中元素以参数来进行拼接;不改变原数组。

var arr = [1,2,3,4];//"1234"
var str = arr.join("-----");
console.log(str,arr)

原理实现:

Array.prototype.myJoin=function(separator){
    var str = "";
    if (!this|| !(this.constructor===Array)) return str;
        if (separator === undefined) separator = ",";
        separator = String(separator);
        for (var i = 0; i < this.length; i++) {
            i===this.length-1?str += this[i]:str += this[i] + separator      
        }
        return str;
}
    var arr=[1,2,3,4]
    var item=arr.myJoin("&")
    console.log(arr);
    console.log(item)

concat()合并数组,将参数放到原数组里,如果参数是一个数组,把数组中的元素提出来,放到原数组中。不改变原数组。

Array.prototype.myConcat = function() {
            var arr = JSON.parse(JSON.stringify(this)); 
              // 这里用JSON可以深度拷贝数组
            for (var i = 0; i < arguments.length; i++) {
                var arg = arguments[i]; 
                for ( var j = 0; j < arg.length; j++ ) {
                    arr.push(arg[j]);
                }
            };
            return arr;
        }
        var arr1 = [1,2,3], arr2 = ['a','b','c'];
        console.log("arr1.myConcat(arr2)":arr1.myConcat(arr2));
        console.log("arr1":arr1);
        console.log("arr2":arr2);

toString( )使数组变成字符串,用’,’连接。若数组的值存在数组,会便遍历拼接在字符串里;对象,会变成[object Object];undefined则什么都不连接,返回最后转化的字符串;不会改变原数组。
toLocalString( )使数组变成字符串,用’,’连接。数组内的元素会调用自己的toLocalString方法;返回最后转化的字符串;不会改变原数组。
for遍历数组;(不用for in遍历)


	var arr = ["a","b","c","d"];
		for(var i = 0; i < arr.length; i++){
			console.log(arr[i]);
			}
发布了4 篇原创文章 · 获赞 0 · 访问量 19

猜你喜欢

转载自blog.csdn.net/titbits/article/details/105231470