一个系列带你搞定前端面试的手写代码环节(2) --- call & apply & bind

call

改变this指向用的,可以接受多个参数

 Function.prototype.myCall = function(ctx) {
    
    
    ctx = ctx || window; // ctx 就是 obj
    let fn = Symbol();
    ctx[fn] = this; // this就是foo
    let result = ctx[fn](...arguments);
    delete ctx[fn];
    return result;
}
let obj = {
    
     name: 'CreatorRay' };
function foo() {
    
     return this.name };
// 就是把foo函数里的this指向, 指向obj
console.log(foo.myCall());

/**
 * 用Symbol是因为他是独一无二的, 避免和obj里的属性重名
 * 原理就是把foo添加到obj里, 执行foo拿到返回值, 再从obj里把foo删掉
 * 
 */

apply

原理同上,只不过apply接受第二个参数是数组,不支持第三个参数

Function.prototype.myApply = function(ctx) {
    
    
    ctx = ctx || window;
    let fn = Symbol();
    ctx[fn] = this;
    let result;
    if(arguments[1]) {
    
    
        result = ctx[fn](...arguments[1]);
    }else {
    
    
        result = ctx[fn]();
    }
    delete ctx[fn];
    return result;
}

bind

Function.prototype.myBind = function(ctx) {
    
    
    const self = this;
    const fn = function() {
    
    };
    const bind = function() {
    
    
        const _this = this instanceof fn ? this : ctx;
        return self.apply(_this, [...args, ...arguments]);
    }
    fn.prototype = this.prototype;
    bind.prototype = new fn();
    return bind;
}

/**
 * bind 不会立即执行, 会返回一个函数
 * >>> 函数可以直接执行并且传参, 如foo.myBind(obj, 1)(2, 3), 所以需要
 * [...args, ...arguments] 合并参数
 * >>> 函数也可以new, 所以要判断原型 this instanceof fn
 * 
 */

call、apply、bind的区别

  • 都可以改变this指向
  • call和apply会立即执行,bind不会,而是返回一个函数
  • call和bind可以接收多个参数,apply只能接收两个,第二个是数组
  • bind参数可以分多次传入

QQ:505417246
微信:18331092918
微信公众号:Code程序人生
个人博客:http://rayblog.ltd

在这里插入图片描述

Guess you like

Origin blog.csdn.net/m0_46171043/article/details/119754438