Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does "Function.call.bind(Function.bind)" mean?

Tags:

javascript

I need your help. I got stuck with these code lines

var bind = Function.call.bind(Function.bind);
bind(CC, Components);

I try to understand what they are and how they work but I cannot :-(

  1. Could someone help to explain clearly how they works? As I understand, "Function.call.bind" will invoke a function which is bind to it via bind(). And "Function.bind" will return a function which is called by "Function.call.bind". Also not sure how "bind(CC, Components)" works. Looks like Components will be bind to CC. Please correct me if I am wrong.
  2. In case I don't want to use Function constructor like that, what should I do to re-write the code above in another way but still keeps the same workflow/logic?

Thank you for your help.

like image 399
Phuong Nguyen Avatar asked Oct 19 '15 15:10

Phuong Nguyen


People also ask

What does the function bind () do?

We use the Bind() method to call a function with the this value, this keyword refers to the same object which is currently selected . In other words, bind() method allows us to easily set which object will be bound by the this keyword when a function or method is invoked.

What is .bind in JavaScript?

bind is a method on the prototype of all functions in JavaScript. It allows you to create a new function from an existing function, change the new function's this context, and provide any arguments you want the new function to be called with.


2 Answers

1. What is Function#bind and standalone bind function?

Function#bind

A call to Function#bind creates a new function that is eternally bound to the context passed as the first argument. Function#bind operates as a method on a function. That is, you can only bind the function that Function#bind is invoked on.

let str = 'Hello, World!'
let fn = () => console.log(this)

// Bind the `this` to be `str`
let boundFn = fn.bind(str)
boundFn() // => 'Hello, World!'

// Attempt re-bind:
boundFn = fn.bind('new str')
boundFn() // => 'Hello, World!'

______

Function#call

Function#call is different to Function#bind in that it executes the given function with a context and any other arguments given. It does not return a new bound function.

let str = 'Hello, '
let fn = (who) => console.log(this + who)
fn.call(str, 'World!') // => 'Hello, World!'

______

Passing a function by reference loses its context

When we pass a function by reference we lose its context. In this case, it means we cannot simply do var bind = Function.bind and call bind as a standalone function.

let log = () => console.log('Hello, World!')
let bind = Function.bind;    
bind(log) // => Uncaught TypeError: Bind must be called on a function

______

Creating a standalone function bind

The code that you shared creates a shorthand (standalone) function that is equivalent to Function#bind but accepts the function to bind as its first argument and the context to bind that function to as its second, rather than invoking the bind method as a member of the function that is being bound (e.g. fn.bind(ctx)).

// Create standalone `bind` function
let bind = Function.call.bind(Function.bind);

let obj = { hello: 'World!' }
let log = () => console.log(this)
let boundFn = bind(log, obj)
boundFn() // => { hello: 'World!' }

______

2. How to achieve this functionality without Function#bind?

The above solution accepts a function and a second argument that defines the returned function's context (this). We can imitate this functionality quite simply with a helper function that accepts the same type of arguments and returns a function that when invoked executes the function with the given context and arguments using Function#call.

  1. The function to bind
  2. The context to bind the function to

For example:

function bind (fn, ctx) {
    return function (...args) {
        fn.call(ctx, ...args);
    };
}

Note that this isn't quite the same as creating a bound function. You can read about what happens during the creation of a bound function in 9.4.1.3 BoundFunctionCreate in the spec.

like image 71
sdgluck Avatar answered Sep 24 '22 18:09

sdgluck


  1. The context of a function is determined by how it is called, so in order for the shorthand bind to work correctly, you must generate a function where this is Function.bind. Note the signature of call:

    .call(thisArg[, arg1[, arg2[, ...]]])
    

    So this execution returns a function bound to Function.bind. In your specific case, it will bind CC to Components, so that when you invoke CC(), the context (this) will be Components.

  2. Per @BenjaminGruenbaum you can do let bind = (fn, ...args) => fn.bind(...args);

like image 45
Mathletics Avatar answered Sep 23 '22 18:09

Mathletics