-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2693-CallFunctionWithCustomContext.js
More file actions
106 lines (92 loc) · 3.65 KB
/
2693-CallFunctionWithCustomContext.js
File metadata and controls
106 lines (92 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// 2693. Call Function with Custom Context
// 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) {
// return this.a + 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
/**
* @param {Object} context
* @param {Array} args
* @return {null|boolean|number|string|Array|Object}
*/
// use apply
Function.prototype.callPolyfill = function(context, ...args) {
//console.log(context);
return this.apply(context, args)
}
// use bind
Function.prototype.callPolyfill1 = function(context, ...args) {
// 使用 bind,IE9 才开始支持。
return this.bind(context, ...args)()
}
// use call
Function.prototype.callPolyfill2 = function(context, ...args) {
// 使用 不能使用的 call
return this.call(context, ...args)
}
// use Symbol
Function.prototype.callPolyfill3 = function(context, ...args) {
const sym = Symbol();
context[sym] = this; // 这里的 this 为调用 call的函数本身
// 将函数绑定到对象上,但是不能让原有的对象真的拥有一个函数,会影响一些函数取键值、取值的结果。
// 将函数绑定到对象的原型上,为了键值唯一,使用Symbol做key,且用后删除。
const res = context[sym](...args);
delete context[sym];
return res;
}
// use Object.defineProperty
Function.prototype.callPolyfill4 = function (context, ...args) {
const that = {
...context,
}
Object.defineProperty(that,'fn',{
value:this,
enumable:false
})
return that.fn(...args)
}
// 在 ...args 语法出现之前,使用 arguments
// Function.prototype.callPolyfill = function (context) {
// return this.apply(context, Array.prototype.slice.apply(arguments, [1]))
// }
/**
* function increment() { this.count++; return this.count; }
* increment.callPolyfill({count: 1}); // 2
*/
function increment() { this.count++; return this.count; }
console.log(increment.callPolyfill({count: 1})); // 2
console.log(increment.callPolyfill1({count: 1})); // 2
console.log(increment.callPolyfill2({count: 1})); // 2
console.log(increment.callPolyfill3({count: 1})); // 2
console.log(increment.callPolyfill4({count: 1})); // 2