手写call、bind、apply(手写代码总结)

1. 手写call、apply和bind
2. 手写防抖和节流
3. 手写函数柯里化
4. 手写rgb转16进制
5. 手写驼峰转换

1. 手写call 、apply和 bind

转载自博文

call

Function.prototype.myCall = function( context ){
    // 1. 判断有没有传入要绑定的对象,没有默认为window;如果是基本类型的话通过Object()方法进行转换
    var context = Object(context) || window;

    // 2. 给context添加一个fn属性,值为this,也就是fn()
    context.fn = this;

    // 3. 保存返回值
    let result = '';

    // 4. 取出传递的参数,第一个参数是this
    // 截取除第一个参数外剩余参数的方法
    const args = [...arguments].slice(1);
    // const args = Array.prototype.slice.call(arguments , 1);
    // const args = Array.from(arguments).slice(1);

    // 5. 执行方法,传入参数
    // ... 是es6的展开数组
    result = context.fn(...args);

    // 6. 删除该属性
    delete context.fn;

    // 7. 返回结果
    return result;
}

// 测试
const obj = {
    value :'hello'
}
function fn(name , age){
    return {
        value : this.value ,
        name , 
        age
    }
}
let res = fn.myCall(obj , 'LL' , 25);
console.log(res) // { value: 'hello', name: 'LL', age: 25 }

apply

Function.prototype.myApply = function( context , args ){
    var context = Object(context) || window;
    context.fn = this;
    let result = '';

    // 4. 判断有没有传入第二个参数 args,如果传入就将第二个参数展开
    if(!args){
        // 没有传入,直接返回该函数
        result = context.fn();
    }else{
        // 传入了,将参数展开
        result = context.fn(...args);
    }

    delete context.fn;
    return result;
}

// 测试用例
const obj = {
    value :'hello'
}
function fn(name , age){
    return {
        value :this.value ,
        name , 
        age
    }
}
let res = fn.myApply(obj ,[ 'LL' , 25]);
console.log(res) // { value: 'hello', name: 'LL', age: 25 }

bind

Function.prototype.myBind = function( context ){
    // 1. 判断this是不是一个函数
    if(typeof this !== 'function'){
        // 不是函数,抛出错误
        throw new Error('不是一个函数');
    }
    // 2. 暂存this
    const self = this;

    // 3. 获取传入的参数
    // 拿到第一组参数,如果没传,是一个空数组
    const args1 = [...arguments].slice(1);

    // 第二次调用bindFn
    const bindFn = function(){
        // 获取第二个参数
        const args2 = [...arguments];
        // 将第一部分参数和第二部分参数合并到一起,进行返回
        return self.apply(context , args1.concat(args2));
    }
    return bindFn
}

// 测试用例
const obj = {
    value :'hello'
}

function fn(name , age){
    return {
        value :this.value ,
        name , 
        age
    }
}
let res = fn.myBind(obj)('HH' , 30);
console.log(res)

2. 手写防抖和节流

转载自 博文

function submit() {
   console.log("submit");
}

防抖

const debounce = (fn, delay) => {
   let timerId = null;
   return (...args) => {
     if (timerId) {
        window.clearTimeout(timerId);
     }
     timerId = setTimeout(() => {
       fn.apply(this, args);
       timerId = null;
     }, delay);
   };
};

const btnDebounce = debounce(submit, 1000);

节流

 const throttle = (fn, delay) => {
      let canUse = true;
      return (...args) => {
        if (canUse) {
          fn.apply(this, args);
          canUse = false;
          setTimeout(() => (canUse = true), delay);
        }
      };
    };

// 间隔设为3秒,效果比较明显
const btnThrottle = throttle(submit, 3000);

3. 手写函数柯里化

函数柯里化定义:

柯里化是指这样一个函数(假设叫做createCurry),他接收函数A作为参数,运行后能够返回一个新的函数。并且这个新的函数能够处理函数A的剩余参数。

eg:

function add(a,b,c){
	return a+b+c
}
function curryAdd(a) {
	return function(b){
		return function(c){
			return a+b+c
		}
	}
}

add(1,2,3)
curryAdd(1)(2)(3)

封装 摘自 博文

 function progressCurrying(fn, args) {
    var _this = this
    var len = fn.length;
    var args = args || [];
    return function() {
        var _args = Array.prototype.slice.call(arguments);
        Array.prototype.push.apply(args, _args);

        // 如果参数个数小于最初的fn.length,则递归调用,继续收集参数
        if (_args.length < len) {
            return progressCurrying.call(_this, fn, _args);
        }
        // 参数收集完毕,则执行fn
        return fn.apply(this, _args);
    }
}

4. 手写rgb转16进制

function rgb2hex(sRGB) {
    var regexp=/rgb\((\d+),\s*(\d+),\s*(\d+)\)/;
    var ret=sRGB.match(regexp);
    if(!ret){
        return sRGB;
    }else{
        var str='#';
        for(var i=1;i<=3;i++){
            var m=parseInt(ret[i]);
            if(m<=255&&m>=0){
                str+=(m<16?'0'+m.toString(16):m.toString(16));
            }else{
                return sRGB;
            }
        }
        return str;
    }
}

5. 手写驼峰转换

function cssStyle2DomStyle(sName) {
    var arr = sName.split('')
    if(arr.indexOf('-')==0) {
        arr.splice(0,1)
    }
    for(var i =0; i<arr.length;i++) {
        if(arr[i]=='-') {
            arr.splice(i,1)
            arr[i]= arr[i].toUpperCase()
        }
    }
    return arr.join('')
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值