code block in curly braces after the function call

Viewed 457

I'm looking over this code (stripped down version of the implementation of createStore within the Redux source code)

function createStore(reducer) {
    var state;
    var listeners = []

    function getState() {
        return state
    }

    function subscribe(listener) {
        listeners.push(listener)

        return unsubscribe() {
            var index = listeners.indexOf(listener)
            listeners.splice(index, 1)
        }
    }

    function dispatch(action) {
        state = reducer(state, action)
        listeners.forEach(listener => listener())
    }

    dispatch({})

    return { dispatch, subscribe, getState }
}

My question is specific to the below block inside

function subscribe(listener)


return unsubscribe() {
   var index = listeners.indexOf(listener)
   listeners.splice(index, 1)
}

The section in the curly bracket

{
   var index = listeners.indexOf(listener)
   listeners.splice(index, 1)
}

does that block gets passed to the unsubscribe() method? any resemblance to Ruby's blocks? how does that work in javascript?

3 Answers

Whan you call subscribe and pass it a listener, it returns you a function which you can call anytime later. Ex:

const {dispatch, subscribe, getState} = createStore(this.myReducer); 
// for demonstration purpose. Now you have references to the values createStore() returns;

const subscription = this.subscribe(this.listener)

Now whenever you call this.subscription() it will execute this:

var index = listeners.indexOf(listener)
listeners.splice(index, 1)

with listener being saved in a closure.

First of all, there are some issues with the code you posted. A better stripped-down version of the createStore() function would be:

function createStore(reducer) {
  var listeners = [];

  function subscribe(listener) {
    listeners.push(listener);

    return function unsubscribe() {
      var index = listeners.indexOf(listener)
      listeners.splice(index, 1)
    };
  }

  return {subscribe};
}

Note that you were forgetting some semicolons and that (EDIT: the OP forgot nothing. Redux skips semicolons to conform to React Router ESLint) the subscribe() method wasn't returning function unsubscribe() but just unsubscribe().

Now, answering the question, this article is a nice lecture to illustrate the differences between Ruby and JavaScript on this topic.

Ruby methods are not functions or first-class citizens because they cannot be passed to other methods as arguments, returned by other methods, or assigned to variables. Ruby procs are first-class, similar to JavaScript’s first-class functions.

In JavaScript functions are truly first-class citizens. They can be passed a round as any other piece of data.

In our example, the createStore() function returns an object, containing the function/method subscribe(). It does so by returning the name of the function (subscribe). Likewise, subscribe() also returns a function, but this time the declaration of that function happens directly inside the return statement. Both are valid ways to pass a function.

When you instantiatecreateStore by a function call, you will obtain the returned object.

var myObject = createStore("foo");

The new object has the method subscribe(). If you call that method you will obtain the unsubscribe() function.

var myFunction = myObject.subscribe("bar");

Of course, you could do it in one line by:

var myFunction = createStore("foo").subscribe("bar");

Try it in the snippet below:

function createStore(reducer) {
  var listeners = [];

  function subscribe(listener) {
    listeners.push(listener);

    return function unsubscribe() {
      var index = listeners.indexOf(listener)
      listeners.splice(index, 1)
    };
  }

  return {subscribe};
}

var myObject = createStore("foo");
console.log(myObject);  // print an object with the subscribe method.
var myFunction = myObject.subscribe("bar");
console.log(myFunction);  // print the unsubscribe function

console.log(createStore("foo").subscribe("bar"));

You might also want to read about objects in MDN.

That block of code is part of the unsubscribe function that is returned by the subscribe method

Related