JavaScript-数组方法重构

前言:

数组API的调用使得我们在js的使用中更加方便和快捷,而今天我们要探索数组API方法的底层原理,接下来和大家一起学习数组中的一些方法重构。
我们主要学习一下,栈与队列方法、迭代方法两种数组API重构。

一、栈与队列方法

  • myPush()
  • myPop()
  • myUnshift()
  • myshift()

1.myPush()

重写push方法()
可接受任意类型的参数,将它们逐个添加到数组的末尾,并返回数组的长度.

//1.在原型中添加自写的push
Array.prototype.myPush = function () {
    //2.使用arguments接收传进来的参数,遍历传进来了多少个
    for (var i = 0; i <= arguments.length-1; i++) {
        //3.将遍历的arguments中的值添加进数组里
        this[this.length] = arguments[i];
    }
    // 4.返回数组的长度
    return this.length;
}
var arr = new Array();
arr = [1, 2, 3, 4, 5];
//例子1:
console.log(arr.myPush(6, 7, 8, 9));//9
console.log(arr);
//[
//     1, 2, 3, 4, 5,
//     6, 7, 8, 9    
//   ]

//例子2:
//console.log(arr.myPush({}));//6
// console.log(arr);//[ 1, 2, 3, 4, 5, {} ]

2.myPop()

重写pop()方法
从数组的末尾移除最后一项,减少数组的length值,返回移除的项

Array.prototype.myPop = function () {
    if (this.length == 0) {
        // 判断数组是否为空
        return undefined;
    }
    //先返回最后一个值
    var last = this[this.length - 1];
    //移除最后一个值
    this.length = this.length - 1;
    return last;
}
var arr = new Array();
//例子1:
arr = [1, 2, 3, 4, 5];
console.log(arr.myPop()); //5
console.log(arr); //[ 1, 2, 3, 4 ]

//例子2:
// arr = [];
// console.log(arr.myPop());//undefined

3.myUnshift()
myUnshift()
方法可向数组的开头添加一个或更多元素,并返回新的长度。

Array.prototype.myUnshift = function () {
    for (var i = this.length + arguments.length - 1; i >= 0; i--) {
        //当i递减循环到小于arguments的长度的时候,
        // 说明数组已经向后移动完成,已经移动到arguments需要的长度的后面了。
        if (this[i] < arguments[i]) {
            //把arguments的值传进去给数组移动玩后空出来的位置
            this[i] = arguments[i];
        } else {
            // 数组一个个向后挪位置,需要移动arguments.length长度,(i减去多少就是要移动多少位置)
            this[i] = this[i - arguments.length];
        }
    }
    return this.length;
}

var arr = new Array();
arr = [1, 2, 3, 4, 5];
console.log(arr.myUnshift(7, 8)); //7=5+2
console.log(arr);
// [
//     7, 8, 1, 2,
//     3, 4, 5
// ]

4.myShift()
shift()方法
移除数组中的第一个项并且返回该项,同时将数组的长度减一。

Array.prototype.myShift = function () {
    var firstElemen = this[0];
    for (var i = 1; i <= this.length - 1; i++) {
        this[i - 1] = this[i];// 将数组一个一个往前挪
    }
    // 长度减一
    this.length = this.length - 1;
    return firstElemen;
}

var arr = new Array();
arr = [7,1,2,3,4,5,6];
console.log(arr.myShift());//7
console.log(arr);//[ 1, 2, 3, 4, 5, 6 ]

二、迭代方法

迭代方法采用的都是回调函数的形式来实现功能。

  • myForEach()
  • myEvery()
  • mySome()
  • myMap()
  • myFilter()

1.myForEach()

方法用于调用数组的每个元素,并将元素传递给回调函数,通常用于遍历。

Array.prototype.myForEach = function (fun) {
    //遍历数组中的每个元素
    for (var i = 0; i < this.length; i++) {
        //将回调函数中的三个参数传进来,遍历出来
        fun(i, this[i], this);
    }
}
var arr = [1, 2, 3];
console.log(arr);//[ 1, 2, 3 ]
var result = arr.myForEach(function (index, item, arr) {
    console.log(index, item, arr)
     //0 1 [ 1, 2, 3 ]
	//1 2 [ 1, 2, 3 ]
   //2 3 [ 1, 2, 3 ]
});

2.myEvery()

只要有一个不符合就返回false,全部符合才返回true
myEvery()方法比较复杂,我们先看看他的雏形,先不看this指针。

// 雏形:
Array.prototype.myEvery = function () {
    for (var i = 0; i < this.length; i++) {
        if (!fun(this[i])) {
            // '数组中的元素只要有一个不满足函数的条件'
           // if(!fun(this[i])){return false};
           //判断条件为当有一个元素不符合回调函数的条件则返回false
            return false;
        }
    }
    // 否则,也就是都满足函数的条件
    return true;
}
var arr = [1, 2, 3, 4, 5];
var result = arr.myEvery(function (item, index, arr) {
    console.log(this);
 // 回调函数有三个参数:this[i](值) i(索引下标) this(指向)
// 而这里我们只需要一个this指向,输出我们需要的内容,在这里没修改指向前是global,
// 添加了第二个参数obj对象{name:xiaoxain}后,this指向修改为我们定义的arr
}, {
    name: xiaoxian
})
console.log(result);

在我们自写的myEvery()方法里,在判断条件中,我们需要判断,是否有传入第二个参数obj(第一个参数是函数,回调函数),如果有,那么我们就通过bind修改this的指向,如果没有那么我们就原样输出。
也就是讲if语句修改为:

if (!(obj?fun.bind(obj)(this[i]):fun(this[i])))

第一开始this指向为global,判断是否有传入第二个参数obj,
如果有则通过bind修改this的指向,这时候this的指向是arr

完善后的代码:

Array.prototype.myEvery = function (fun, obj) {
    for (var i = 0; i < this.length; i++) {
        if (!(obj?fun.bind(obj)(this[i]):fun(this[i]))) {
            return false;
        }
    }
    return true;
}

var arr = [1, 2, 3, 4, 5];
var result = arr.myEvery(function (item, index, arr) {
    console.log(this);
    return item > 0;
   // return item > 2;
}, {
    name: 'xiaoxian'
})
console.log(result);
//{ name: 'xiaoxian' }
//{ name: 'xiaoxian' }
//{ name: 'xiaoxian' }
//{ name: 'xiaoxian' }
//{ name: 'xiaoxian' }
//true

//当return item>2时,结果为:
//{ name: 'xiaoxian' }
//false

3.mySome()

有一个满足条件则返回true,只有全部不满足才返回false
与我们上面写的myEvery()恰恰相反,这时候我们只需要修改if语句的返回值即可,只要有一个满足则返回true。

Array.prototype.mySome = function (fun, obj) {
    for (var i = 0; i < this.length; i++) {
        if ((obj ? fun.bind(obj)(this[i]) : fun(this[i]))) {
            return true;
        }
    }
    return false;
}
var arr = [1, 2, 3, 4, 5];
var result = arr.mySome(function (item, index, arr) {
    console.log(this);
    return item > 2;
}, {
    name: 'xiaoxian'
})
console.log(result);
//{ name: 'xiaoxian' }
//{ name: 'xiaoxian' }
//true

myEvery()与mySome()方法输出的结果来看,
**myEvery()**遇到不满足的条件时,就会立刻停止打印,例如myEvery()给出的第二个例子,return item>2时,遍历到2时,不满足条件,立刻停止,不继续打印,所以只打印了第一次;
**mySome()**方法,如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。遍历到第二个数字2>1,返回true,满足条件之后就不继续打印了,所以打印了两次,一次是1的打印,一次是2的打印。

4.myMap()

方法返回一个新的数组,数组中的元素为原始数组元素调用函数处理后的值.

Array.prototype.myMap = function (fun, obj) {
	//创建一个空的数组来接受函数处理后的元素的值
    var newArr= [];
    for (var i = 0; i < this.length; i++) {
    //遍历后判断数组中的元素是否满足函数的需求,如果是则返回true,否则false
        newArr.push(obj ? fun.bind(obj)(this[i]) : (fun(this[i])))
    }
    return newArr;
}
var arr = [1, 2, 3, 4, 5];
var result = arr.myMap(function (item, index, arr) {
    console.log(this); 
    return item > 2;
}, {
    name: 'xiaoxian'
})
console.log(result);
// { name: 'xiaoxian' }
// { name: 'xiaoxian' }
// { name: 'xiaoxian' }
// { name: 'xiaoxian' }
// { name: 'xiaoxian' }
// [ false, false, true, true, true ]

5.myFilter()

方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

Array.prototype.myFilter = function (fun, obj) {
//创建一个空的数组来接受函数处理后的元素
    var newArr= [];
    for (var i = 0; i < this.length; i++) {
        if (obj ? fun.bind(obj)(this[i]) : fun(this[i])) {
        //如果符合条件那么就将元素放入新建的数组内
            newArr.push(this[i]);
        }
    }
    //返回数组
    return newArr;
}
var arr = [1, 2, 3, 4, 5];
var result = arr.myFilter(function (item, index, arr) {
    console.log(this); //执行五次而不是三次[ false, false, true, true, true ]
    return item > 2;
}, {
    name: 'xiaoxian'
})
console.log(result);
// { name: 'xiaoxian' }
// { name: 'xiaoxian' }
// { name: 'xiaoxian' }
// { name: 'xiaoxian' }
// { name: 'xiaoxian' }
// [ 3, 4, 5 ]

总结:

说实话第一次看到的时候比较难懂,但是多敲几遍,多看几遍,多理解几遍,你就会开窍了,别说话,多练!

你可能感兴趣的:(数组方法重构,javascript)