02-使用自定义上下文调用函数

#题目描述#

增强所有函数,使其具有 callPolyfill 方法。该方法接受一个对象 obj 作为第一个参数,以及任意数量的附加参数。obj 成为函数的 this 上下文。附加参数将传递给该函数(即 callPolyfill 方法所属的函数)。

例如,如果有以下函数:

function tax(price, taxRate) {
  const totalCost = price * (1 + taxRate);
  console.log(`The cost of ${this.item} is ${totalCost}`);
}
调用 tax(10, 0.1) 将输出 "The cost of undefined is 11" 。这是因为 this 上下文未定义。

然而,调用 tax.callPolyfill({item: "salad"}, 10, 0.1) 将输出 "The cost of salad is 11" 。this 上下文被正确设置,函数输出了适当的结果。

请在不使用内置的 Function.call 方法的情况下解决这个问题。

#示例# 

1、示例1

输入:
fn = function add(b) {
  return this.a + b;
}
args = [{"a": 5}, 7]
输出:12
解释:
fn.callPolyfill({"a": 5}, 7); // 12
callPolyfill 将 "this" 上下文设置为 {"a": 5} ,并将 7 作为参数传递。

2、示例2 

输入:
fn = function tax(price, taxRate) { 
 return `The cost of the ${this.item} is ${price * taxRate}`; 
}
args = [{"item": "burger"}, 10, 1,1]
输出:"The cost of the burger is 11"
解释:callPolyfill 将 "this" 上下文设置为 {"item": "burger"} ,并将 10 和 1.1 作为附加参数传递。

#提示#

typeof args[0] == 'object' and args[0] != null
1 <= args.length <= 100
2 <= JSON.stringify(args[0]).length <= 105

 #题目解析# 

1、准入准出:增强所有函数,使其具有 callPolyfill 方法,其中prototype可以用于动态增强对象,那么有些js的原生类,没有提供我们想要的功能的时候,我们就可以用prototype对其增强

/**
 * @param {Object} context
 * @param {Array} args
 * @return {null|boolean|number|string|Array|Object}
 */
Function.prototype.callPolyfill = function(context, ...args) {
    // ....逻辑代码
}

2、 参数定义:其中obj作为第一个参数,是函数的上下文context,其余的参数个数不定通过...args来表示。

3、结果解析:当第一个参数为null时,说明callPolyfill函数里this上下文未定义,我们需要让window来作为函数的默认上下文,如果传入了一个对象obj,则可以直接作为函数上下文。

将函数添加到传入的对象中成为对象的一个方法,通过对象调用该方法便可以隐式绑定this为该对象,获取返回值后将对象新增的方法删除,使对象恢复如初。
为了防止新增方法覆盖对象原来的属性/方法,可以使用symbol产生唯一的key。

#答案解析# 

/**
 * @param {Object} context
 * @param {Array} args
 * @return {null|boolean|number|string|Array|Object}
 */
Function.prototype.callPolyfill = function(context, ...args) {
    let cxt = context || window;
    // 如果context对象里已经有fn属性,则容易被覆盖,故最好使用唯一的key
    cxt.fn = this;
    // 这边改使用key的时候,最好每次拿到函数执行返回值后,对新增的属性进行删除
    return cxt.fn(...args);
}
/**
 * @param {Object} context
 * @param {Array} args
 * @return {null|boolean|number|string|Array|Object}
 */
Function.prototype.callPolyfill = function(context, ...args) {
  const sym = Symbol();
  context[sym] = this; // 这里的this为调用call的函数本身
  const res = context[sym](...args);
  delete context[sym];
  return res;
}

关联博客:call、apply、bind 的深度解析 

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端-张冠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值