尝试重写数组API

170 阅读1分钟

1. pop()

Array.prototype.myPop = function () { 
    var lastchild = this[this.length - 1]   //理解这两个this
        // var data = this   
        // var lastchild = data[data.length - 1] 
    if (this.length == 0) {
        return undefined
    } else{
        this.length--
    }
    return lastchild
}

const arr = [1,2,3,4,5];
var a = arr.myPop();
console.log(a,arr);   // 5 [ 1, 2, 3, 4 ]

2. push()

Array.prototype.myPush = function () {
    var newlen = this.length + arguments.length;
    for ( i = 0; i < arguments.length; i++) {
        this[newlen - arguments.length + i] = arguments[i];
        // 等价于 this[this.length] = arguments[i];
    }
    return newlen;
}
var arr = [1, 3, 5];
var a = arr.myPush(7, 9, 11);
console.log(a, arr);   // 6 [1, 3, 5, 7, 9, 11]

ECMAScript中的参数在内部是用一个数组来表示的。在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数。

3. shift()

Array.prototype.myShift = function () {
    const first = this[0];
    for (let i = 0; i < this.length; i++) {
        this[i] = this[i + 1];
    }
    this.length--;
    return first
}
const arr = [1, 3, 5, 7, 9];
const a = arr.myShift();
console.log(a, arr);   // 1 [ 3, 5, 7, 9 ]

4. unshift()

Array.prototype.myUnshift = function () {
    var newlen = this.length + arguments.length;
    for (i = newlen-1; i >= 0; i--) {
        if (i > arguments.length - 1) {   
            this[i] = this[i - arguments.length]
        }
        else {
            this[i] = arguments[i];
        }
    }
    return newlen;
}
var arr = [1, 3, 5];
var a = arr.myUnshift(8, 1, 8);
console.log(a, arr);   // [8, 1, 8, 1, 3, 5]

5. sort()

quickSort

function quickSort(nums) {
    if (nums.length <= 1) {
        return nums
    }
    let pivotIndex = Math.floor(nums.length / 2)
    let pivot = nums.splice(pivotIndex, 1)[0]
    let left = [],
        right = []
    nums.forEach((element) => {
        if (element < pivot) {
            left.push(element)
        } else {
            right.push(element)
        }
    })      
    return quickSort(left).concat(pivot, quickSort(right))
}
let nums = [8, 1, 8, 5, 2, 0]
console.log(quickSort(nums));  // [ 0, 1, 2, 5, 8, 8 ] 

bubbleSort

function swap(myArray,p1,p2){
    var temp = myArray[p1]
    myArray[p1] = myArray[p2]
    myArray[p2] = temp
}
function bubbleSort(myArray){
    let len = myArray.length - 1
    for(i = 0; i < len; i++){
        for(j = 0; j < len - i; j++){
            if(myArray[j] > myArray[j + 1]){
                swap(myArray, j, j + 1)
            }
        }
    }
    return myArray
}
var nums = [8, 1, 2, 5, 0]
console.log(bubbleSort(nums));   // [ 0, 1, 2, 5, 8 ]

selectionSort

function selectionSort(nums){
    let len = nums.length
    let min = 0
    let temp
    nums.forEach((element,i) => {
        min = i
        for(j = i + 1; j < len; j++){
            if(nums[j] < nums[min]){
                min = j
            }
        }
        temp = nums[i]
        nums[i] = nums[min]
        nums[min] = temp
    })
    return nums
}
let nums = [2,9,6,8,1,4]
console.log(selectionSort(nums));

6. slice()

Array.prototype.mySlice = function(start,end){
    let result = []
    for(i = start; i < end; i++){
        result.push(this[i])
    }
    return result
}
let arr = [2,9,9,6,8,1,4]
let result = arr.mySlice(2,5)
console.log(result);  // [9, 6, 8]

7. indexOf()

Array.prototype.myIndexOf = function(item, start = 0){
    for(let i = start; i < this.length; i++){
        if(item == this[i]) return i;
    }
    return -1;
}
  let arr = ["Banana","Orange","Apple","Mango","Banana","Orange","Apple"];
  let result = arr.myIndexOf("Apple", 3)
  console.log(result)  // 6

8. some()

Array.prototype.mySome = function (foo, obj) {  
    for (i = 0; i < this.length; i++) {
                    //call(obj, this[i])  bind(obj)(this[i])
        if (obj ? foo.apply(obj, [this[i]]) : foo(this[i])) {   
            return true;
        }
    }
    return false;
}
var arr = [1, 3, 5, 7];
var result = arr.mySome(function(i) {
    console.log(this);
    return i > 5
}, {a: 'a'})
console.log(result);

注意:if (obj ? foo.apply(obj, [this[i]]) : foo(this[i]))。这条语句主要是为了实现 thisArg 这个API功能:改变回调函数内的this指向。

arr.some(callback(element[, index[, array]])[, thisArg] )

[参数]

  • callback 用来测试每个元素的函数,接受三个参数:
  • element 数组中正在处理的元素。
  • index (可选) 数组中正在处理的元素的索引值。
  • array (可选)
  • some() 被调用的数组。
  • thisArg(可选)执行 callback 时使用的 this 值。

9. every()

Array.prototype.myEvery = function (foo, obj) {
    for (i = 0; i < this.length; i++) {
        // (!(obj?foo.bind(obj)(this[i]) :foo(this[i])))
        if (!(foo.bind(obj)(this[i])) ){      
            return false;
        }
    }
    return true;
}
var arr = [1, 3, 5, 7];
var result = arr.myEvery(i => i > 5)
console.log(result);  // false

10. map()

Array.prototype.myMap = function(fn){
    let data = []
    for(let i = 0; i < this.length; i++){
        data.push(fn(this[i], i, this))
        // data.push(fn.call(this[i], i))
    }
    return data
}

console.log([1,2,3].myMap((item, i, arr) => {
    console.log(i);
    console.log(arr);
    return item * item
}));

11. filter()

const data = [1, 2, 3, 4, 5].filter(i => i < 3)

Array.prototype.myFilter = function (fn) {
    const data = [];
    for (let key in this) {
        fn.call(null, this[key]) && data.push(this[key])
    }
    return data;
}
 const data1 = [1,2,3,4,5].myFilter(i => i <= 3)  
 console.log(data1)   // [1, 2, 3]