Javascript : Passing variables from parent function to child function

Viewed 1259

I wanted to pass many variables to child functions and that passed variables should also pass on to the next child functions. Passing them each time as parameters is a tedious job. I was wondering what would be the better way to do this in Js. I tried using the this keyword , But not sure if that is the correct way of usage to achieve this.

var scriptConfig = {
  availableOptions: {
    version: "1",
    type: "one",
    status: "free",
  },
  availableCategories: {
    navbar: true,
    hasCoupon: true
  }
};

window.addEventListener('load', function() {
  let options = scriptConfig.availableOptions;
  let version = options.version;
  renderDashboard(options, version);
});

function renderDashboard(options, version) {
  createNavbar(options, version);
}

function createNavbar(options, version) {
  console.log(options);
  console.log(version);
}

Using this

var scriptConfig = {
  availableOptions: {
    version: "1",
    type: "one",
    status: "free",
  },
  availableCategories: {
    navbar: true,
    hasCoupon: true
  }
};

window.addEventListener('load', function() {
  this.options = scriptConfig.availableOptions;
  this.version = options.version;
  this.renderDashboard();
});

function renderDashboard() {
  this.createNavbar();
}

function createNavbar() {
  console.log(this.options);
  console.log(this.version);
}

Can anyone suggest which would be a better way ? Also it would be great if anyone suggest better coding practice for the above lines of code.

3 Answers

There is [apply()][1] function in JS.

It lets you specify what this is when calling a function and provide additional arguments.

Well if you are constantly passing a variable from one function to its child functions, or in other terms from one ui component to its ui component, what you are doing in this case is sharing context between these entities (functions, components, or call them whatever you want depending on the type of their output)

global variables should be avoided, however in certain use cases they are the only valid solution, one use case for global variables are contexts - some people differentiate between context and global state, in that a context is a read only, while global state is mutable, for managing global states, javascript has many libraries that handle this like redux.

Assuming that you are using an immutable context, then the best option is a global variable, obviously you should hide that global variable behind a getter function to also make code more decelarticve

// Assuming you are using javascript modules if not just remove the export keyword
// obviously add the needed properties for the object
const globalContext = Object.freeze({}) // freeze object to prevent mutations to it
export const getGlobalContext = () => {
    // hiding the global variable behind a getter offers two advantages, it better conveys the message that this object should not mutated by code
    // later it enables more customization of context sharing, if for example later you decide to nest contexts, but if your context will get complicated, then doing that through a library should be better option
    return globalContext;
}

Finally dont use the this keyword outside of instances/classes context, this will produce poor code that is hard to read, and more prone to errors, and its one of the reasons ES6 added the syntatic sugar class to make code that uses this only use it there and not in normal functions ( though it is still valid syntax)

Using this in global scope (outside class) is not a good idea as it pollute the Window object. I will suggest you to create a class and wrap everything like this:

class Dashboard {
    constructor(config) {
        this.options = config.availableOptions;
        this.version = this.options.version;
    }

    renderDashboard() {
        this.createNavbar();
    }

    createNavbar() {
        console.log(this.options, this.version);
    }
}

var scriptConfig = {
    availableOptions: {
        version: "1",
        type: "one",
        status: "free",
    },
    availableCategories: {
        navbar: true,
        hasCoupon: true
    }
};

window.addEventListener('load', function () {
    const dashboard = new Dashboard(scriptConfig);
    dashboard.renderDashboard();
});
Related