仿写部分JavaScriptApi

call实现

/**
 * call 实现
 * * 本质就是拿到传递的参数进行调用
 *   利用this 指向来改变调用者
 * */
Function.prototype.hjhCall = function (){
    var rst = null,
        obj = arguments[0] || window,  //拿到第一个参数
        len = arguments.length, //拿到arguments长度
        argArr = [];
    //组合传递过来的参数 'arguments[' + i + ']'  ==》'arguments[1]
    for (let i = 1; i < len; i++) {
        argArr.push('arguments[' + i + ']');
    }
    //保存this 当前this 指定的是 call前一个函数
    obj.targetFunc = this;
    //利用eval当函数和参数互相组合
    rst = eval('obj.targetFunc(' + argArr.join() + ')');
    //删除原函数obj.targetFunc
    delete obj.targetFunc;
     return rst;
}

es6 call 实现

/**
 * es6 call 实现
 * 本质就是拿到传递的参数进行调用
 * 利用this 指向来改变调用者
 * */
Function.prototype.es6Call = function (){
    var rst= null,
        obj = arguments[0] || window,  //拿到第一个参数
        args = [...arguments].slice(1); //去掉第一个参数
    obj.targetFunc = this; //将调用者绑在这个参数身上
    //执行
    rst = obj.targetFunc(...args) //this绑定本质谁调用指向谁。
    delete obj.targetFunc
    return rst
}

apply 实现

/**
 *  apply 实现
 * 本质就是拿到传递的参数进行调用
 * apply 第二个参数是数组,所以需要处理
 * 利用this 指向来改变调用者
 * */
Function.prototype.hjhapply = function (){
    //拿到参数因为apply是个数组
    var obj =arguments[0] ||window, //获取传入的对象
        len =arguments[1] && arguments[1].length, //获取参数的长度,
        argArr = [], //定义参数组
        rst = null;
   		obj.targetFunc = this; //保存这个函数
    //如果参数不存在则直接执行
    if(arguments[1]){
        // 循环参数
        for (let i = 0; i < len; i++) {
            argArr.push(argArr.push('arguments[1][' + i + ']'));
        }
        rst = eval('obj.targetFunc(' + argArr.join() + ')');
    }else {
        //没有参数直接执行函数
        rst =  obj.targetFunc()
    }
    delete obj.targetFun
    return rst
}

bind 实现

  • 无参情况
/**
 - bind 实现  bind返回的是一个函数
 - */
Function.prototype.hjhbind =function (target){
        var self = this
        var f =function (){
            // return self()
            return self.apply(target ||window)
        }
        return f
}
  • 返回的函数不带参数执行
/**
 - bind 实现  bind返回的是一个函数
 - */
Function.prototype.hjhbindpar =function (target){
        var self = this;
        //bing传递的参数
        var args = [].slice.call(arguments,1)
        console.log("hjhbindpar",args)
        var f =function (){
            // return self()
            return self.apply(target ||window,args)
        }
        return f
}
  • 返回得函数带参数执行
/**
 - bind 实现  bind返回的是一个函数
 - 带参数的情况
 - 并且再次调用返回的函数方法并且传递参数时
 - */
Function.prototype.hjhbindpars =function (target){
        var self = this;
        //bing传递的参数
        var args = [].slice.call(arguments,1)
        var f =function (){
            var _arg = [].slice.call(arguments,0);
            return self.apply(target ||window,args.concat(_arg))
        }
        return f
}
  • 返回调用构造函数情况
    Function.prototype.newhjhbindpars =function (target){
        var self = this;
        //bing传递的参数
        var args = [].slice.call(arguments,1)
        var temp = function (){}
        var f =function (){
            var _arg = [].slice.call(arguments,0);
            //  console.log(this instanceof temp)
            // console.log(this)
            return self.apply(this instanceof temp?this:(target ||window),args.concat(_arg))
        }
        //原型链继承
        temp.prototype = self.prototype;
        f.prototype = new temp();
        return f
}

flat 降维数组

Array.prototype.flatten = function (){
   return  this.reduce((pre,cur)=>{
        /**
         * 核心,利用reduce方法循环数组中的每个值,
         * reduce,传入一个默认的空数组
         * 判断 cur 如果是数组,说明需要递归
         *  用pre的值连接递归返回的结果
         *     不是数组,pre 连接cur
        * */
        return Object.prototype.toString.call(cur) === '[object Array]'?pre.concat(cur.flatten()):pre.concat(cur)
    },[])
}

push

Array.prototype.hjhpush = function (){
    for (const argumentsKey in arguments) {
        //     console.log(arguments[argumentsKey])
        // console.log(this.length)
        this[this.length] = arguments[argumentsKey]
    }
    return this
}

pop() 方法用于删除并返回数组的最后一个元素

Array.prototype.hjhpop =function (){
    var arr = [],
        len = this.length - 1,
        popResult = this[len];
    /*方法一 start */
    for (let i = 0; i < len; i++) {
        //深度拷贝原数组
        arr.push(this[i]);
    }
    this.length = 0; //利用length = 0, 把原数组清空
    for (let i = 0; i < len; i++) {
        this.push(arr[i]);
    }
    return popResult; //功能:返回踢掉
}

pop2() 方法用于删除并返回数组的最后一个元素

Array.prototype.hjhpop2 =function (){
    var result;
    if(this.length){
        //拿到最后一个值
        result = this[this.length-1]
        //利用length删除最后一个值
        this.length--
    }
   return   result
}

shift 删除并返回数组的第一个元素

Array.prototype.hjhshift = function (){
    var arr =[],
        len = this.length,
    result =this[0];
    for (let i = 1; i <len ; i++) {
        arr.push(this[i])
    }
    this.length =0;
    for (let i = 0; i <len-1 ; i++) {
        this.push(arr[i])
    }
    return result
}

shift2 删除并返回数组的第一个元素

Array.prototype.hjhshift2 = function (){
    var arr ,
        len = this.length,
        result =this[0];
    //slice 裁减一下
    arr = this.slice(1);
    this.length =0;
    for (let i = 0; i <len-1 ; i++) {
        this.push(arr[i])
    }
    return result
}

unshift 向数组的开头添加一个或更多元素,并返回新的长度。

/**
 * 思路:
 *  保存参数并转为数组-->
 *  保存原数组-->原数组清空-->
 *  参数先push -->
 *  原数组push-->
 *  返回数组
 * */
Array.prototype.hjhunshift =function (){
    //存储参数
    let arr = [];
    let len = this.length;
    let arglen = arguments.length;
    //存储原数组
    for (let i = 0; i < len; i++) {
          arr.push(this[i])
    }
    this.length = 0; //清空原数组
    //给原空数组添加参数
    for (let i = 0; i < arglen; i++) {
        this.push(arguments[i])
    }
    //在合并原数组
    for (let i = 0; i < len; i++) {
        this.push(arr[i])
    }
    return this
}

unshift2 向数组的开头添加一个或更多元素,并返回新的长度。

/**
 * unshift
 * 思路:
  将类数组转化成真正的数组,并连接现在的数组
 *  清空原数组-->
 *  循环写入数据即可
 *  返回数组
 * */
Array.prototype.hjhunshift2 = function (){
     let arr = Array.prototype.slice.call(arguments).concat(this);
     let len = arr.length;
     this.length =0;
    for (let i = 0; i <len ; i++) {
        this.push(arr[i])
    }
    return this
}

join 拼接数组

/**
 * 思路:
 *   默认连接符为‘,’如果传入其他字符则按照其他字符来连接,
 *   在连接过程中剔除了undefined和null如果里面是字符的话
 *   如果值不是原始值,则隐式调用tostring方法转化为字符串
 *  返回数组
 * */
Array.prototype.hjhjoin =function (){
    var targetStr = arguments[0], //那才参数值
        str = ',',  //默认值为逗号
        result = this[0], //获取起一个值
        len = this.length; //获取长度
    //判断 targetStr 的值如果不存在str就是默认值,如果存在就判断是不是空的
    if (targetStr !== undefined) {
        if (targetStr === null) {
            str = 'null'
        } else {
            str = targetStr.toString();
        }
    }
    for (let i = 1; i < len; i++) {
         //剔除空和undefined
        if (this[i] !== undefined && this[i] !== null) {
            result += (str + this[i]);
        } else {
            result += str;
        }
    }
    return result;
}

concat 数组连接生成新的数组

/**
 * 思路:
 *  创建新的数组,保存旧的数组写入数据
 * */
Array.prototype.hjhconcat = function (){
    const arr = [],
        len =this.length,
        arlen = arguments.length;
    // 写入新数组
    for (let i = 0; i < len; i++) {
            arr.push(this[i])
    }
    for (let i = 0; i <arlen ; i++) {
        //数组展开要推入,多为数组之展开第一层,如果里面数组或者对象修改时可能影响原来的值
        if(Object.prototype.toString.call(arguments[i]) =='[object Array]'){
            let arrlen =  arguments[i].length;
            for (let j = 0; j <arrlen ; j++) {
                arr.push(arguments[i][j]);
            }
        }else  {
            arr.push(arguments[i])
        }
    }
    return arr

}

reverse 反转数组

/**
 * 思路:
 *  创建新的数组,保存旧的数组倒叙写入数据
 * */
Array.prototype.hjhreverse = function (){
    let arr =[],
        len =this.length
    for (let i = len-1; i >=0 ; i--) {
        arr.push(this[i])
    }
    this.length =0;
    for (let i = 0; i <arr.length ; i++) {
        this.push(arr[i])
    }
    return arr
}

forEach 循环数组

/**
 * 思路:
 *  传入数组 循环调用回调函数即可,
 *  this 指向如果不存在则指向当前默认的this即可
 * */
Array.prototype.hjhforEach =function (fn){
        var _arr = this,
        len = this.length,
         //拿到第二个参数为this指向
        params02 = arguments[1] || window; //this函数执行时的指向(严格模式指向undefined怎么办?)
        for (let i = 0; i <len ; i++) {
         fn.apply(params02,[_arr[i],i,_arr])
    }
}

forEach源码是这样写的

Array.prototype.hjhforEach2 =function (callback, thisArg){
     var T,K;
     if (this == null){
         throw  new TypeError('this is null or not defined')
     }
     //构造函数创建一个对象包装器
     var O = Object(this);
     //获取这个对象的长度
     var len =O.length >>>0;
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function');
    }
    //当arguments.length > 1 T为 undefined 所以不改变this指向
    if (arguments.length > 1) {
        T = thisArg;
    }
    K = 0;
    while (K<len){
        var kValue;
        //如果k
        if(K in O){
            //拿到其中一个值
            kValue =O[K]
            //执行回调函数改变this指向
            callback.call(T,kValue,K,O)
        }
        K++
    }
}

filter(源码) 过滤函数返回符合条件的数据

Array.prototype.hjhfilter = function(func, thisArg) {
    'use strict';
    // console.log(typeof func === 'Function',typeof func === 'function')
    if ( ! ((typeof func === 'Function' || typeof func === 'function') && this) )
        throw new TypeError();
        //拿到数组的长度
    var len = this.length >>> 0,
        //创建一个等长的数组
        res = new Array(len), // preallocate array
        //定义当前的this,
        t = this, c = 0, i = -1;
    // 如果thisArg 不存在证明不用改写this指向
    if (thisArg === undefined){
         //如果i+1 不等于len的长度 也就是数组从0开始 到数组的长度结束
        while (++i !== len){
            //判断 i在不在当前的数组的 范围内
            if (i in this){
                //如果func(t[i], i, t) 根据返回值决定是否保存数据
                if (func(t[i], i, t)){
                    res[c++] = t[i];
                }
            }
        }
    }
    else{
        //如果i+1 不等于len的长度 也就是数组从0开始 到数组的长度结束
        while (++i !== len){
            //判断 i在不在当前的数组的 范围内
            if (i in this){
                //当前需要改写this的指向如果func(t[i], i, t) 没有返回值则不保存数据 有返回值保存数据
                if (func.call(thisArg, t[i], i, t)){
                    res[c++] = t[i];
                }
            }
        }
    }

    res.length = c; //修改长度
    return res;
};

仿写 filter 认定有this的情况

Array.prototype.hjhfilter2 = function (fn){
     var _arr = this,
         len = this.length,
         seif = arguments[1]
        newarr =[];
    for (let i = 0; i < len; i++) {
        fn.apply(seif,[_arr[i],i,_arr]) ?newarr.push(_arr[i]) :''
    }
    return newarr
}

map 仿写 返回一个新的数组

Array.prototype.hjhmap =function (fn){
    var _arr =this,
        len = this.length,
        self = arguments[1],
        newarr= [];
    for (let i = 0; i < len; i++) {
         newarr.push(fn.apply(self,[_arr[i],i,_arr]))
    }
    return newarr
}

every 判断每个值是否符合回调函数的值

Array.prototype.hjhevery = function (fn){
     var _arr =this,
         len = this.length,
         self = arguments[1],
         result = true;
    for (let i = 0; i < len; i++) {
         // console.log(fn.apply(self,[_arr[i],i,_arr]))
            if(!fn.apply(self,[_arr[i],i,_arr])){
                return false
        }
    }
    return  result
}

some 判断数组中是否存在,并返回结果

Array.prototype.hjhsome = function ( fn){
    var _arr =this,
        len = this.length,
        self= arguments[1],
        result = false;
    for (let i = 0; i <len; i++) {
        let as = fn.apply(self, [_arr[i], i, _arr])
        if(as){
            result=  true
            break
        }
    }
    return  result
}

reduce 仿写

Array.prototype.hjhreduce =function (fn,initVal){
            var _arr =this,
                len = this.length,
                self = arguments[2],
                res =initVal;
        for (let i = 0; i <len ; i++) {
            //本次调用的res 就是上一次结果的返回值
            res =  (fn.apply(self,[res,_arr[i], i, _arr]))
        }
        return res
}

reduceRight 仿写

Array.prototype.hjhreduceRight =function (fn,initVal ){
     var _arr = this,
         len = this.length,
         self =arguments[2],
         res =initVal;
    for (let i = len-1; i >=0 ; i--) {
        res =  (fn.apply(self,[res,_arr[i], i, _arr]))
    }
    return res
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值