跳至主要內容

2693. 使用自定义上下文调用函数


2693. 使用自定义上下文调用函数open in new window

🟠   🔗 力扣open in new window LeetCodeopen in new window

题目

Enhance all functions to have the callPolyfill method. The method accepts an object obj as it's first parameter and any number of additional arguments. The obj becomes the this context for the function. The additional arguments are passed to the function (that the callPolyfill method belongs on).

For example if you had the function:

function tax(price, taxRate) {
	const totalCost = price * (1 + taxRate);
	console.log(`The cost of ${this.item} is ${totalCost}`);
}

Calling this function like tax(10, 0.1) will log "The cost of undefined is 11". This is because the this context was not defined.

However, calling the function like tax.callPolyfill({item: "salad"}, 10, 0.1) will log "The cost of salad is 11". The this context was appropriately set, and the function logged an appropriate output.

Please solve this without using the built-in Function.call method.

Example 1:

Input:

fn = function add(b)

args = [{"a": 5}, 7]

Output: 12

Explanation:

fn.callPolyfill({"a": 5}, 7); // 12

callPolyfill sets the "this" context to {"a": 5}. 7 is passed as an argument.

Example 2:

Input:

fn = function tax(price, taxRate) { return The cost of the ${this.item} is ${price * taxRate}; }

args = [{"item": "burger"}, 10, 1.1]

Output: "The cost of the burger is 11"

Explanation: callPolyfill sets the "this" context to {"item": "burger"}. 10 and 1.1 are passed as additional arguments.

Constraints:

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

题目大意

增强所有函数,使其具有 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:

输入:

fn = function add(b)

args = [{"a": 5}, 7]

输出: 12

解释:

fn.callPolyfill({"a": 5}, 7); // 12

callPolyfill 将 "this" 上下文设置为 {"a": 5} ,并将 7 作为参数传递。

示例 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 <= 10^5

解题思路

要实现 callPolyfill 方法,可以通过将要调用的函数临时添加为对象的一个方法,然后使用这个方法来调用函数。以下是详细的实现思路:

  1. 定义 callPolyfill 方法:将其添加到 Function.prototype,使所有函数都能访问这个方法。

    • 第一个参数是 context,表示函数调用时的 this 上下文。
    • 后面的参数是传递给原始函数的参数 args
  2. 将函数赋值给对象

    • context 中临时创建一个唯一的 Symbol 属性,因为 Symbol 属性在迭代中不可枚举;
    • 将 Symbol 属性指向要调用的函数,可以使用 this 来引用当前函数。
  3. 调用函数:使用临时创建的方法调用它,传入附加参数。

  4. 清理:调用后,从 context 中删除临时属性,确保不会对 context 产生影响。

  5. 返回结果:如果函数有返回值,可以将其返回。

复杂度分析

  • 时间复杂度O(1),只进行了一次函数调用。
  • 空间复杂度O(1),只使用了常数级的空间来存储临时方法和结果。

代码

/**
 * @param {Object} context
 * @param {Array} args
 * @return {null|boolean|number|string|Array|Object}
 */
Function.prototype.callPolyfill = function (context, ...args) {
	// 创建一个唯一的 Symbol 属性
	const uniqueId = Symbol();
	// 将当前函数临时赋值为对象的方法
	context[uniqueId] = this;
	// 调用函数并传递参数
	const result = context[uniqueId](...args);
	// 清理临时属性
	delete context[uniqueId];
	return result;
};

/**
 * function increment() { this.count++; return this.count; }
 * increment.callPolyfill({count: 1}); // 2
 */