手写简单的call bind apply

call

js 复制代码
  const Person1 = {
    fullName: function (country, city) {
      return this.firstName + this.lastName + " " + country + " " + city
    }
  }
  const Person2 = {
    firstName: "张",
    lastName: "三",
  }
  Person1.fullName.call(Person2, '中国', '河南') // 张三 中国 河南 

call的作用是改变了那个被执行的方法(也就是调用call的那个方法)的直接调用者!

而这个被执行的方法内部的this也会重新指向那个新的调用者,就是call方法所接收的第一个obj参数。

还有两个特殊情况就是当这个obj参数为null或者undefined的时候,this会指向window。

js 复制代码
Function.prototype.myCall = function (obj) {
    // 保存this 谁调用的myCall,this就指向谁,指向obj1.fun
    obj.fn = this
    // 保存参数
    let args = Array.from(arguments).slice(1)
    // 调用函数
    let result = obj.fn(...args)
    // 删除fn属性
    delete obj.fn
    return result
}
var obj1 = {
    num: 20,
    fun: function (n) {
        return this.num + n
    }
};
var obj2 = {
    num: 15,
};
let res = obj1.fun.myCall(obj2, 10)
console.log(res);

apply

js 复制代码
  const person = {
    fullName: function (country, city) {
      return this.firstName + this.lastName + " " + country + " " + city
    }
  }
  const newPerson = {
    firstName: "壮",
    lastName: "志国",
  }
  person.fullName.apply(newPerson, ['中国', '河南']) // 壮志国 中国 河南
js 复制代码
Function.prototype.myApply = function (obj) {
    let result
    // 保存this 谁调用的myCall,this就指向谁,指向obj1.fun
    obj.fn = this
    // 是否传参
    if (arguments[1]) {
        result = obj.fn(...arguments[1])
    } else {
        result = obj.fn()
    }
    delete obj.fn
    return result
}
var obj1 = {
    num: 20,
    fn: function (n, m) {
        return this.num + n + m
    }
};
var obj2 = {
    num: 15,
};
let res = obj1.fn.myApply(obj2, [10, 20])
console.log(res);

bind

js 复制代码
  const person = {
    fullName: function (country, city) {
      return this.firstName + this.lastName + " " + country + " " + city
    }
  }
  const newPerson = {
    firstName: "壮",
    lastName: "志国",
  }
   // 打印出fullName函数
  person.fullName.bind(newPerson, '中国', '河南')() // 壮志国 中国 河南
js 复制代码
Function.prototype.myBind = function (obj) {
    // 这里的 this/self 指的是需要进行绑定的函数本身,比如用例中的 man
    const self = this;
    // 获取 myBind 函数从第二个参数到最后一个参数(第一个参数是 obj)
    // 这里产生了闭包
    const args = Array.from(arguments).slice(1)
    return function () {
        // 这个时候的 arguments 是指 myBind 返回的函数传入的参数
        const bindArgs = [...arguments]
        // 合并
        return self.apply(obj, [...args, ...bindArgs]);
    };
};

const person = {
    name: 'zyj'
}

function man(age) {
    console.log(this.name);
    console.log(age)
}

const test = man.myBind(person)
test(18)//zyj 18
相关推荐
sugar__salt22 分钟前
从网页小游戏到数据可视化:掌握 HTML5 Canvas 核心能力
前端·信息可视化·html5
北极星日淘27 分钟前
前端 i18n 中日双语交互 + 翻译客服接口联动方案|日系海淘平台中文友好化开发实战
前端·交互
現実逃避と1 小时前
WIN10 Edge连续关闭多个标签页导致资源管理器崩溃临时解决办法
前端·edge
jay神1 小时前
基于 FastAPI + Vue 的宠物领养管理系统
前端·vue.js·python·毕业设计·fastapi·宠物
lichenyang4531 小时前
鸿蒙 Web 容器(五·完结):闭环回传、容器治理,兼谈 AtomicServiceEnhancedWeb
前端
lichenyang4531 小时前
鸿蒙 Web 容器(四):ArkTS 拿到请求后,怎么「按 action 找能力」?
前端
lichenyang4531 小时前
鸿蒙 Web 容器(三):H5 怎么「调」到 ArkTS?
前端
代码不加糖2 小时前
Proxy能够监听到对象中的对象的引用吗?
开发语言·前端·javascript
光影少年2 小时前
react 原理与进阶
前端·react.js·掘金·金石计划
kyrie282 小时前
Vue 全套性能优化方案
前端