Let's say i have a function
function getSum (firstValue) { return firstValue + this.secondValue }
and some class
class TestClass {}
how can i dynamically assign function getSum
to class prototype with binding firstValue as 1, so after
// some code like TestClass.prototype.getSum = getSum.bind(null, 1)
const obj = new TestClass()
obj.secondValue = 2
console.log(obj.getSum()) // 3
i could get 3
For object i could do it like this
obj.getSum = getSum.bind(obj, 1)
But for TestClass.prototype
i can not set first parameter of bind because context is not existing yet
Can this puzzle be solved directly?
Indirectly i can do something like this
const firstValue = 1
TestClass.getSum = function () {
return getSum.bind(this, firstValue)()
}
or like this
TestClass.firstValue = 1
TestClass.getSum = function () {
return getSum.bind(this)(TestClass.firstValue)
}
but may be it can be done more directly
Thanks in advance
You can create a function that takes one parameter will call getSum
but supplies the first parameter itself.
TestClass.prototype.getSum = function() { //<–– normal function
return getSum.call( this, 1 );
// ^^^^ ^^^^ ^
// || || |
// forward this –++––––++ +–––––– pass a value for the first parameter
}
This gets you the following
function getSum (firstValue) { return firstValue + this.secondValue }
class TestClass {}
TestClass.prototype.getSum = function() {
return getSum.call(this, 1);
}
const obj = new TestClass()
obj.secondValue = 2
console.log(obj.getSum()) // 3
In general this the process where you supply bind a value to a parameter in the function is called partial application. If a function takes three parameters, for example, you can only set two at first and expect the final one at a later point. The whole process can be abstracted away by creating a function to handle this:
function partiallyApply(fn, ...params) {
return function(...moreParams) {
return fn.call(this, ...params, ...moreParams);
}
}
function takes4Parameters (a, b, c, d) {
return a + b + c + d;
}
const takes2Parameters = partiallyApply(takes4Parameters, 1, 2); // 1 + 2 + c + d
console.log("1 + 2 + 11 + 12 =", takes2Parameters(11, 12));
const takes1Parameter = partiallyApply(takes2Parameters, 3); // 1 + 2 + 3 + d
console.log("1 + 2 + 3 + 5 =", takes1Parameter(5));
const takesNoParameter = partiallyApply(takes1Parameter, 6); // 1 + 2 + 3 + 6
console.log("1 + 2 + 3 + 6 =", takesNoParameter());
Using that higher order function, we can more easily derive the getSum
method for TestClass
function getSum (firstValue) { return firstValue + this.secondValue }
function partiallyApply(fn, ...params) {
return function (...moreParams) {
return fn.call(this, ...params, ...moreParams)
}
}
class TestClass {}
TestClass.prototype.getSum = partiallyApply(getSum, 1);
//example of adding other partially applied methods:
TestClass.prototype.getSum2 = partiallyApply(getSum, 2);
TestClass.prototype.getSum3 = partiallyApply(getSum, 3);
TestClass.prototype.getSum4 = partiallyApply(getSum, 4);
const obj = new TestClass()
obj.secondValue = 2
console.log(obj.getSum()); // 3
console.log(obj.getSum2()); // 4
console.log(obj.getSum3()); // 5
console.log(obj.getSum4()); // 6