js call方法实现原理

前言

我们知道call方法可以改变this的指向
使用方法如下

const book = '《十万个为什么》'
function log() {
    console.log('这本书是' + this.book)// this默认指向全局window对象
}
log() // 这本书是《十万个为什么》

const instance = {book:'《从你的全世界路过》'}
// 改变this指向instance
log.call(instance)// 这本书是《从你的全世界路过》

log函数中使用了this关键字,this默认指向window的原因是,声明一个函数时都默认挂在window身上
而后通过call方法使this执行了新的对象instance

this指向问题

到这里就不得不聊一聊,this到底指向谁,怎么判断?怎么修改this指向?
简单来说就是,一个方法被"谁"调用,this就指向"谁"
这里的"谁"可以是一个对象、一个数组、甚至是一个函数

因为在js里边,万物皆对象。

举个栗子:

const jay = {
    name: 'jay',
    sayhello() {
        console.log('Nice to see you, I am ' + this.name);
    }
}
jay.sayhello()// Nice to see you, I am jay
const cindy = {
    name: 'cindy',
    sayhello() {
        console.log('Nice to see you, I am ' + this.name);
    }
}
jay.sayhello()// Nice to see you, I am cindy

const list = [1, 2, 3]
list.sayhello = () => {
    console.log('Nice to see you, I have ' + this.length + 'items');
}
list.sayhello()// Nice to see you, I have 3 items

可以看到,谁调用了sayhello,this就指向谁

call实现原理

那么call是如何改变this指向的呢?
手写一个$call,避免覆盖原生call方法

/**
 * call实现原理
 */
Function.prototype.$call = function (context,...args) {
    const fn  = this // 调用call方法的目标函数
    context.fn = fn // 函数挂到目标对象身上
    context.fn(...args)// 执行fn并传参,这时候this已经执行context了,因为fn是contex调用的
    delete context.fn// 记得删除fn,不要污染原对象
}
// 使用方法
function say(name) {
    console.log(name + this.age + '岁了');
}
const obj = { age: 23 }
say.$call(obj, 'sea')// sea23岁了
  • 任意函数只要调用了$call方法,就会被挂载到新的对象context上去,
  • 然后调用context里边的临时fn,这样就会把this指向context
  • 最后删除临时fn是为了保证不改变原来的对象

apply实现原理

与call的实现原理相同,就是传参的方式略微不同。传的是一个数组。

Function.prototype.$apply = function (context,args = []) {
    const fn  = this
    context.fn = fn
    context.fn(...args)
    delete context.fn
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值