Arsene Wenger
Arsene Wenger

Reputation: 659

export a variable inside a function to be used in other modules

I'm quite new to programming. I have spent the last 3 days trying to figure out this problem, so any help would be greatly appreciated.

I have access to clientID inside a for loop. (Please look at the last line in the code below). There is only one ClientID which I'm successfully able to print.

I want this client ID to be exported from this module so that I can use it in other modules.

import { Configurations } from './models';

type MethodNames = 'init' | 'event';

export const DEFAULT_NAME = '_hw';

interface LoaderObject { 
    q: Array<[MethodNames, {}]>;
}

export default (
    win: Window,
    defaultConfig: Configurations,
    scriptElement: Element | null,
    render: (element: HTMLElement, config: Configurations) => void
) => {
 
    const instanceName =
        scriptElement?.attributes.getNamedItem('id')?.value ?? DEFAULT_NAME;
    const loaderObject: LoaderObject = win[instanceName];
    if (!loaderObject || !loaderObject.q) {
        throw new Error(
            `Widget didn't find LoaderObject`);
    }

    if (win[`loaded-${instanceName}`]) {
        throw new Error(
            `Widget already loaded`)
        );
    }

    let targetElement: HTMLElement;


    for (let i = 0; i < loaderObject.q.length; i++) {
        const item = loaderObject.q[i];
        const methodName = item[0];
        console.log(methodName);
        if (i === 0 && methodName !== 'init') {
            throw new Error(
                `Failed to start Widget`);
        } else if (i !== 0 && methodName === 'init') {
            continue;
        }
      
        const valueObject = Object.assign(defaultConfig, item[1]);
        const clientID = valueObject.clientID
        console.log("ClientID", clientID)
    }

//rest of the code.... 

I have also tried this. defined a variable clientID outside the for loop and then storing value from inside the for loop. But on printing, I'm getting undefined

var clientID;
console.log("....last Client ID", clientID)
   const valueObject = Object.assign(defaultConfig, item[1]);
    clientID = valueObject.clientID

Upvotes: 3

Views: 15947

Answers (3)

Naeio
Naeio

Reputation: 1181

Your issue is about your variables' scopes. Let's start with a simpler version, without for loop:

default export (a: object) => {
    const variableToExport = a;
}

The reason why you can't directly access variableToExport is that it is defined inside the function, and not outside. To deal with it, you have 2 solutions:

1. Assign to a variable in the outer scope.

The code would look like:

/!\ Read the text below before using this snipplet /!\

export let variableToExport;

default export (a: object) => {
    variableToExport = a;
}

Here, you're strictly speaking exporting the variable. Since it's defined outside the function, you can access it outside the function and thus, you can export it. HOWEVER, IT COULD BE A MISTAKE. If you call twice the exported function with different values for a, the variable variableToExport would only have the value corresponding to the second call, and not the first. If the value of variableToExport should not depend on a, it could be OK, but otherwise it seems risky.

2. Returning the value

Since your function would be called to get the variableToExport, you could return it:

default export (a: object) => {
    const variableToExport = a;
    return variableToExport;
}

In case you have multiple things to return, you can build an object to return them all:

default export (a: object) => {
    const retValue = {
        "variableToExport": a,
        ... other variables to return
    }
    return retValue;
}

Then, you can access it from another module (with or without a destructuring assignment):

import foo from 'path/to/module'

const { variableToExport, otherVariable } = foo(a);

This second way is safer than using a "global" variable, as the variableToExport can't have a value that correspond to another call to the function.


Now, for the case of your variable in the for loop, you have a similar issue: you can't access to the variable outside the for loop:

default export (bar: array) => {
    for (const elem of bar) {
        const clientID = elem.clientID;
    }
    return clientID; // Nope, clientID does not exist here
}

To deal with that, the first option works:

default export (bar: array) => {
    let clientID; // Not const, because it will change
    for (const elem of bar) {
        clientID = elem.clientID;
    }
    return clientID;
}

This will thus return the last clientID (and since you said you have only one clientID, it should be ok), but it would be a little better of you could get the value of clientID outside the loop, except if you intend on exporting only the last value of clientID.

I hope that, even though you might not understand everything, you understand how to export the client ID you want to export, and that the key words I gave you allows you to easily find what you might need on the internet more easily than these 3 last days. Ask me if anything isn't clear enough, I'll answer when I'll have time

Upvotes: 5

Gesy Darati
Gesy Darati

Reputation: 113

I guess the way you can access the variable is by creating a let variable outside the loop then assign it a value in the loop, or create an array outside the loop and push values into it inside the loop, that way you can have access to the variable outside the loop's scope.

Upvotes: 0

Kemal PEHLİVAN
Kemal PEHLİVAN

Reputation: 11

I think your problem is about your variable's scope. const is block-scoped so everything about clientID variable happens inside the for loop and does not affect outside. I guess you can use var or let up to your purpose. This is a quite explanatory article about difference between var, let, and const: https://www.freecodecamp.org/news/var-let-and-const-whats-the-difference/

MDN Document on const: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

Upvotes: 1

Related Questions