简体   繁体   中英

What is the role of the this variable when it comes to function currying using the .bind()?

I came across to the following JS code (ES5) and I don't really I understand what is the meaning of the this variable.

function multiply(a,b){
  return a * b;
}

var multipleByThree = multiply.bind(this,3);

multipleByThree(10) // outputs 30

I do understand that the bind copies the multiply function and that 'a' parameter of it, will have the value 3. But what is the purpose of the this variable?

Can you help me out please?

The this variable that you are providing to .bind() is the context. In your case, this refers to the global object space.

Here's an example of how this works:

 var message = 'within global context'; function multiply(a,b){ console.log(this.message); return a * b; } var someOtherContext = { message: 'within some other context' }; var multipleByThree = multiply.bind(this,3); var multipleByThreeOtherContext = multiply.bind(someOtherContext, 3); console.log(multipleByThree(10)) console.log(multipleByThreeOtherContext(10)) 

By changing the context that multiply executed within, we can change what variables it references.

The first argument to bind must be the thisArg :

 fun.bind(thisArg[, arg1[, arg2[, ...]]]) 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

That is, whatever the keyword this inside multiply will refer to. Since multiply doesn't use this at all, it's irrelevant what it refers to. You must still pass something as the first argument to bind , so likely the developer simply chose this (whatever that refers to in this code is unknown to us), but they could just as well have used false , null or anything else.

In javascript this is some kind of "reserved keyword" which refers to current object of the scope.

If this used outside of any object - it refers to window object.
Inside eventhandlers this refers to the DOM object which raised an event.

bind function provide possibility to define which object this will refer inside bound function.

For example if you using this inside function

const calculate = function (price, amount) {
    return (price * amount) - this.discount;
};

You can bound a function with predefined this

const calculateWithDiscount = calculate.bind({ discount: 100 });

const total = calculateWithDiscount(1000, 2); // return 1900

When you bound function which doesn't use this object, you can easily pass null there, which clearly "tell" other developers your intents about using this in the function.

const add = function (a, b) {
    return a + b;
};
const add5 = add.bind(null, 5);

const result = add5(19); // return 24

bind Method (Function) (JavaScript)

For what it's worth, you can do currying without relying upon Function.prototype.bind

Once you stop relying upon this in JavaScript, your programs can start looking like beautiful expressions

 const curry = f => x => y => f (x,y) const mult = (x,y) => x * y const multByThree = curry (mult) (3) console.log (multByThree (10)) // 30 


For a more generic curry implementation that works on functions of varying arity

const curry = (f, n = f.length, xs = []) =>
  n === 0
    ? f (...xs)
    : x => curry (f, n - 1, xs.concat ([x]))

If you want to bellyache about the exposed private API, hide it away with a loop – either way, this is not required to write functional programs in JavaScript

const loop = f =>
  {
    const recur = (...values) =>
      f (recur, ...values)
    return f (recur)
  }

const curry = f =>
  loop ((recur, n = f.length, xs = []) =>
    n === 0
      ? f (...xs)
      : x => recur (n - 1, xs.concat ([x])))

it fixes 3 as the first argument, the arguments of the new function will be preceded by 3

 function multiply(a,b){ console.log(a, b); console.log(arguments) return a * b; } var multipleByThree = multiply.bind(console.log(this),3); console.log(multipleByThree(10)) // outputs 30 console.log(multipleByThree(10, 15)) // outputs 30 

passing this would provide a copy of this(ie the global object) with the preceded arguments list

For more information check out the MDN docs

In the context of Currying the this object in the code presented has no purpose other than as a placeholder . You could replace this with the string "cats" if you wanted and still get the same result. It is simply there to occupy the first argument position and I think it is very misleading to use it in the context of either currying or partial application when using bind. It is better to replace it with the null keyword.

In the case of this example it will pass in the global object and the rest of the code will simply ignore that value since the keyword 'this' is not present within the multiply function itself.

MDN shows a use case, visit https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind and scroll to the section headed Partially applied functions.

ES6 (aka es2015) has improved on the way this code is written by using arrow functions and the code can now be reduced to the following

const multiply = a => b => a * b

const multiplyByThree = multiply(3)

const result = multiplyByThree(10)
console.log(result)
// => 30

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM