JS原生实现API

Array

1、forEach

Array.prototype.mockForEach = function(callback) {
    for(let i = 0;i<this.length;i++){
        callback(this[i],i,this)
    }
}

2 、map

Array.prototype.mockMap = function(callback){
    const mapArr = [];
    for(let i = 0;i<this.length;i++){
        mapArr.push(callback(this[i],i,this))
    }
    return mapArr
}

3、filter

Array.prototype.mockFilter = function(callback){
    const filterArr = [];
    for(let i = 0;i<this.length;i++){
        callback(this[i],i,this) && filterArr.push(this[i]) 
    }
    return filterArr
}

4、every

Array.prototype.mockEvery = function(callback){
    let flag = true;
    for(let i = 0;i<this.length;i++){
        flag = callback(this[i],i,this)
        if(!flag) break
    }
    return flag
}

5、some

Array.prototype.mockSome = function(callback){
    let flag = false;
    for(let i = 0;i<this.length;i++){
        flag = callback(this[i],i,this)
        if(flag) break;
    }
    return flag
}

6、reduce

Array.prototype.mockReduce = function(callback,initValue){
   let start = 0; //如果没有initValue,则从数组第一个元素充当,并从第二个元素开始遍历
   let pre;
   if(initValue){
       pre = initValue
   }else{
       pre = this[0];
       start = 1;
   }
   for(let i = 0;i<this.length;i++){
       pre = callback(pre,this[i],i,this)
   }
   return pre;
}

7、findIndex

Array.prototype.mockFindIndex = function(callback){
    for(let i = 0;i<this.length;i++){
        if(callback(this[i],i,this)){
            return i;
        }
    }
    return -1   //找不到要返回-1
}

8、find

Array.prototype.mockFind = function(callback){
    for(let i = 0;i<this.length;i++){
        if(callback(this[i],i,this)){
            return this[i]
        }
    }
    return undefined;
}

9、fill

Array.prototype.mokeFill = function(value,start = 0,end){
    end = end || this.length;
    for(let i = start;i<end;i++){
        this[i] = value;
    }
    return this
}

10、includes

用处:查找元素,查到返回true,反之返回false,可查找NaN

Array.prototype.mockIncludes = function(value,start = 0){
    if(start<0) start = start + this.length
    const isNaN = Number.isNaN(value)
    for(let i = start;i<this.length;i++){
        if(this[i] === value || Number.isNaN(this[i])=== isNaN){
            return true
        }
    }
    return false
}

11、join

Array.prototype.mockJoin = function(breakSign = ','){
    let str = '';
    for(let i = 0;i<this.length;i++){
        str = i === 0?`${str}${this[i]}`:`${str}${breakSigh}${this[i]}`
    }
    return str
}

12、flat

Array.prototype.mockFlat = function(num = 1){
    if(!Number(num) || Number(num)<0){
        return this
    }
    let flatArr = [];
    for(let i = 0;i<this.length;i++){
        if(Array.isArray(this[i])){
            flatArr = flatArr.concat(this[i].mockFlat(--num))
        }else{
            flatArr.push(this[i])
        }
    }
    return flatArr
}

13、splice

顺序:

1、拷贝删除的元素

2、挪动删除元素后面的元素

3、如果有插入操作,插入新元素

Array.prototype.mockSplice = function(start,cutOutLength,...values){
    const spliceArr = [];
    const backUpArr = [...this]
    start = start < 0 ? this.length - 1 + start : start
    //拷贝获取裁剪的元素
    for(let i = start;i<start+cutOutLength;i++){
        spliceArr[i - start] = backUpArr[i];
    }
    //挪动删除元素后面的元素
    //1、删除的长度比插入长(向前挪)
    if(cutOutLength > values.length){
        for(let move = start + cutOutLength;move<this.length;move++){
            let moveForm = move;
            let moveTo = move - (cutOutLength - values.length)
            if(moveForm in this){
                this[moveTo] = this[moveForm]
            }else{
                delete this[moveTo]
            }
        }
    }else if(cutOutLength < values.length){
    //2、插入的长度比删除的长(向后挪)
        for(let move = this.length-1;move>= start + cutOutLength ;move--){
              let moveForm = move;
            let moveTo = move + (values.length - cutOutLength);
            if(moveForm in this){
                this[moveTo] = this[moveForm]
            }else{
                delete this[moveTo]
            }
        }
    }
    //插入新元素
    for(let add = 0;add < values.length;add++){
        this[start + add] = values[add];
    }
    return spliceArr
}

Object

1、fromEntries

用处:跟entries相反,将键值对数组转成对象

Object.prototype.mockfromEntries = function(arr){
    const fromEntriesObj = {}
    for(let i = 0;i<arr.length;i++){
        const [key,value] = arr[i];
        obj[key] = value
    }
    return fromEntriesObj
}

2、entries

用处:将对象转成键值对数组

注意点:for in会查找到原型链上,所以要做hasOwnProperty的判断

Object.prototype.mockEntries = function(obj){
    const entriesArr = []
    const keyArr = Object.getOwnPropertyNames(obj);
    if(keyArr.length){
        for(let i = 0;i<keyArr.length;i++){
            entriesArr.push([keyArr[i],obj[keyArr[i]]])
        }
    }
    return entriesArr
}

3、keys

Object.prototype.mockKeys = function(obj){
    const keysArr = Object.getOwnPropertyNames(obj);
    return keysArr
}

4、values

Object.prototype.mockValues = function(obj){
    const valuesArr = [];
    const keysArr = Object.getOwnPropertyNames(obj)
    for(let i = 0; i<keysArr.length;i++){
        valuesArr.push(obj[keysArr[i]])
    }
    return valuesArr
}

5、instanceOf

实例于

function mockInstanceOf(child,father){
    const grandFather = father.prototype
    child = child.__proto__
    while(true){
        if(child === null){
            return false;
        }
        if(grandFather === child){  //如果实例元素的祖先有
            return true;
        }
        child = child.__proto__ //遍历实例元素
    }
}

6、assign

Object.prototype.mockAssign = function(target,...args){
    if(target === null || target === undefined){
        throw new TypeError('Cannot convert undefined or null to object')
    }
    mockTarget = Object(target)
     for (let nextObj of args) {
        for (let key in nextObj) {
            nextObj.hasOwnProperty(key) && (mockTarget[key] = nextObj[key])
        }
    }
    return mockTarget
}

Function

1、call

用处:改变this的指向

思路:当obj.fn被执行时,fn的this指向obj,从而修改this的指向

Function.prototype.mockCall = function(context = window,...args){
    //保证fn的唯一
    const fn = Symbol()
    //保证context为对象
    context = context instanceof Object ? context : {};
    context.fn = this //将需要修改this的方法赋值给ctx.fn, 当这个方法执行,则this就会指向ctx
    const calledFunction = context.fn(...args)
    // 避免污染context,使用完需要删除该属性
    delete context.fn 
    return calledFunction
}

2、apply

用处:改变this指向,但是参数以数组的形式传入

思路:同上

Function.prototype.mockApply = function(context = window,arg){
    //保证fn的唯一
    const fn = Symbol()
    //保证context为对象
    context = context instanceof Object ? context : {};
    context.fn = this //将需要修改this的方法赋值给ctx.fn, 当这个方法执行,则this就会指向ctx
    const applyFunction = context.fn(...arg)
    // 避免污染context,使用完需要删除该属性
    delete context.fn 
    return applyFunction
}

3、bind

用处:返回一个绑定函数,并将方法的this指向这个函数

Function.prototype.mockBind = function(context = window){
    return (...args)=>{this.call(obj,...args)}
}

String

1、slice

String.prototype.mockSlice = function(start = 0,end){
    start = start < 0 ? this.length + start : start
    end = !end && end !== 0 ? this.length : end
    if(start >= end) return '';
    let sliceStr = ''
    for(let i = start;i<end;i++){
        sliceStr += this[i]
    }
    return sliceStr
}

2、substr

String.prototype.mockSubstr = function(start = 0,length){
    if(length<0) return '';
    start = start < 0 ? this.length + start : start;
    length = (!length && length !== 0) || length > this.length - start ? this.length : start + length
    let str;
    for(let i = 0;i<length;i++){
        str += this[i]
    }
    return str;
}

3、substring

String.prototype.mockSubString = function(start = 0,end){
    start = start < 0 ? this.length + start : start
    end = !end && end !== 0 ? this.length : end

    if (start >= end) [start, end] = [end, start]
    let subStringStr = ''
    for (let i = start; i < end; i++) {
        str += this[i]
    }

    return subStringStr
}

Promise