手写JS代码

(1) call的实现

Function.prototype.myCall = function(context,...args){

    const ctx= context || window; // 需要绑定到的上下文环境,无则默认为window

    const func = Symbol(); // 使用Symbol定义,避免重复key值

    ctx[func] = this; // 此时this为传入的待执行的函数,使用对象属性的方式存储起来

    // 通过执行对象的函数,使得this指向该对象,即传入的context上下文
    const res = args.length > 0 ? ctx[func](...args):ctx[func]();

    delete ctx[func]; // 执行完清除存储的待执行函数

    return res;

} 

// 验证
function A(x,y){
    console.log(this,x,y)
}

function B(){}

A(); // window,undefined,undefined
A.call(B,1,2); // ƒ B(){} 1 2
A.myCall(B,1,2); // ƒ B(){} 1 2

(2) apply的实现

Function.prototype.myApply = function(context,args=[]){
 
   const ctx= context || window; // 需要绑定到的上下文环境,无则默认为window

    const func = Symbol(); // 使用Symbol定义,避免重复key值

    ctx[func] = this; // 此时this为传入的待执行的函数,使用对象属性的方式存储起来

    // 通过执行对象的函数,使得this指向该对象,即传入的context上下文
    const res = args.length > 0 ? ctx[func](...args):ctx[func]();

    delete ctx[func]; // 执行完清除存储的待执行函数

    return res;

} 

// 验证
function A(x,y){
    console.log(this,x,y)
}

function B(){}

A(); // window,undefined,undefined
A.apply(B,[1,2]); // ƒ B(){} 1 2
A.myApply(B,[1,2]); // ƒ B(){} 1 2

(3) bind 的实现

Function.prototype.myBind = function(){

    const func = this; // 当前待执行的函数
    const ctx = [].shift.call(arguments); // this指向需要改为参数列表传入的第一个值
    const args = arguments; //  arguments此时包含除上下文之外的其他参数

    // 返回新的待执行的函数(已改变this指向)
    return  function newFn(...newArgs){
    
        // 如果新的上下文指向已经是当前原型对象的实例,则无需更改指向
        if (this instanceof newFn) {
            return new func(...args, ...newFnArgs)
        }

        return func.apply(ctx,[...args,...newArgs])
    }
}

// 验证1
function A(x,y){
    console.log(this)
    console.log('x:',x,' y:',y);
}

function B(){}

A(); // window  x: undefined  y: undefined
A.myBind(B)(1,2) // ƒ B(){} x: 1  y: 2
A.myBind(B)([1,2]) // ƒ B(){} x: [1, 2]  y: undefined


// 验证2
function A(x,y,...restNum){
    console.log(this, 'x:',x,  ' y:',y,  ' restNum:',restNum)
}

function B(){}

// 4,5为args,1,2,3为newArgs
A.myBind(B,4,5)(1,2,3) // ƒ B(){} "x:" 4 " y:" 5 " restNum:" [1, 2, 3]

(4) new的实现

function myNew(){
    const obj = {};  // 创建一个新的空对象
    const ctx = [].shift.call(arguments); // 获取到父类的上下文
    obj.__proto__ = ctx.prototype; // 将父类的原型对象绑定到新的对象上
    
    const args = arguments;
    const res = ctx.apply(obj,args); // 使this指向新对象以此执行Parent的构造函数
    
    return res instanceof Object ? res: obj; // Parent构造函数有返回值则使用res否则返回新对象
}

function father(name){ this.name = name; }
var son = myNew(father,'cwh')

console.log(son instanceof father) // true
console.log(son.name) // cwh
console.log(son.__proto__ === father.prototype) // true

(5) promise的实现

https://github.com/CWH0908/MyPromise

(6) instanceOf的实现

function myInstanceOf(son,father){
    let left = son.__proto__;
    const right = father.prototype;
    while(true){
        if(left === null){
            return false;
        }
        if(left === right){
            return true;
        }
        left = left.__proto__;
    }
}

function father(){};
var son = new father();
myInstanceOf(son,father); // true

(7) object.create()的实现

Object.prototype.myCreate = function(obj){

    // 新声明一个函数
    function func(){};

    // 将函数的原型指向obj
    func.prototype = obj;

    // 返回这个函数的实例化对象
    return new func();

}

// 验证代码
var source= {val: 1};
var test = Object.myCreate(test);
 
test.val = 2;
console.log(test.val); // 2 
delete test.val;
console.log(test.val); // 1,沿着原型链找到source对象的属性val

(8) Object.assign的实现

Object.myAssign = function(target,...source){
    if(typeof target === 'undefined' || target === null){
        return new TypeError('target不能传入undefined或null')
    }
    let res = Object(target)
    // 遍历传入的对象数组
    source.forEach(obj=>{
        if(obj){
            // obj非空,遍历
            for(const key in obj){
                if(obj.hasOwnProperty(key)){
                    res[key] = obj[key];
                }
            }
        }
    })
    return res;
}
var a = {name:'a'}
Object.myAssign(a,{name:'b',age:20},{age:30}) // {name: "b", age: 30}

(9) promise.all的实现

Promise.myAll = function(promiseArr){
    let count = 0; // 存储当前成功的个数
    let result = []; // 存储返回成功的数据
    return new Promise((resolve,reject)=>{
        // 遍历传入的数组
        promiseArr.forEach(item=>{
            Promise.resolve(item).then(res=>{
                result[count] = res;
                count++;
                // 全部成功,返回
                if(count === promiseArr.length){
                    resolve(result)
                }
            },err=>{
                // 有一个失败,返回
                reject(error);
            })
        })
    })

}

Promise.myAll([
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.resolve(3),
]).then((res) => {
  console.log("res:", res); // res: [1,2,3]
});

(10) Promise.race的实现

Promise.myRace = function(promiseArr){
    return new Promise((resolve,reject)=>{
        promiseArr.forEach(item=>{
            Promise.resolve(item).then(res=>{
                resolve(res);
            },err=>{
                reject(err);
            })
        })
    })
}

Promise.myRace([
    new Promise((resolve,reject)=>{
        setTimeout(_=>{
            return resolve(111)},
        1000)}),
    Promise.resolve(222)
]).then(res=>{
    console.log('res:',res); // res:222
})

(11) Array.flat的实现

function myFlat(arr){
    return arr.reduce((pre,next)=>{
        return pre.concat(Array.isArray(next)?myFlat(next):next)
    },[])
}

let arr = [1,2,[3,4,[5,[6]]]]
console.log(myFlat(arr)) // [1, 2, 3, 4, 5, 6]

(12) Debounce的实现

function myDebounce(func,delay=500){
    let timer; // 初始化定时器

    return function(...args){
        clearTimeout(timer); // 每次调用函数,清除之前的定时器
        timer = setTimeout(_=>{
            func(...args);
        },delay)
    }
}

// 测试代码
function test(e,text){
    console.log(e.target.innerWidth,e.target.innerHeight,text)
}

window.addEventListener('resize',myDebounce(e=>{test(e,'哈哈哈')},1000))

(13) Throttle的实现

function myThrottle(func,delay=500){
    let noRun = true; // 初始化,当前函数未执行
    return function(...args){
        if(noRun){
        noRun = false; // 执行当前函数
            setTimeout(_=>{
                func(...args);
                noRun = true; // 函数执行完毕
            },delay)

        }
    }
}

// 测试代码
function test(e,text){
    console.log(e.target.innerWidth,e.target.innerHeight,text)
}

window.addEventListener('resize',myThrottle(e => {test(e,'哈哈')},1000))

参考文章:一文帮你搞定90%的JS手写题

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值