1

I have a JS function as below

// A simple array where we keep track of things that are filed.
filed = [];

function fileIt(thing) {
  // Dynamically call the file method of whatever 'thing' was passed in.
  thing.file();

  // Mark as filed
  filed.push(thing);
}

Now, function fileIt(thing) is working well when called as below

fileIt(AuditForm);

Whereas, its giving error at line thing.file(); when i am trying to pass a variable like below

var formID = obj.id;
fileIt(formID);

Variable formID has same value and i.e. "AuditForm" what's wrong here. Kindly suggest.

Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
Lara
  • 2,821
  • 7
  • 39
  • 72
  • It's because `obj.id` is a *string* value, whereas when you hard code `AuditForm` it's a reference to the variable which holds, presumably, an object which has a `file()` method. There are solutions to this problem, but without a clear example of your code we can't really guide you any further. – Rory McCrossan Apr 30 '19 at 09:05
  • This is because `formID` is probably a **Number** or a **string**. Numeric/String types have no `.file` prototype. – briosheje Apr 30 '19 at 09:05
  • @RoryMcCrossan Your assumptions are correct so my question here is how can i make `formID` similar to `AuditForm`, instead of hardcoding i need to pass it as variable as multiple options may be available – Lara Apr 30 '19 at 09:06
  • "AuditForm" is just a string but AuditForm is an object when used directly. – AZ_ Apr 30 '19 at 09:06
  • @briosheje yes, that's correct, its a string, is there any way to convert it to the required format? – Lara Apr 30 '19 at 09:07
  • @AZ_ is it possible to convert `string` into `Object` in JS? – Lara Apr 30 '19 at 09:08
  • @Lara `fileIt` method accepts a "thing". We have no clue what this "thing" should be, but I guess it is meant to be `AuditForm`, assuming it's a **global variable**. If so, you can only use `window[formID]` to access it in your context, otherwise you need to rely on `eval(formID)` which I wouldn't recommend whatsoever. You should refactor your code to properly access what you need and understand what the type of that function is. – briosheje Apr 30 '19 at 09:10
  • 1
    it's just a name of the object, not the stringified object so no you cannot. however you can create another factory object which have the {name: object} like properties and you can use the same as factoryObject[obj.id] and pass the same in function. – AZ_ Apr 30 '19 at 09:12

1 Answers1

1

If obj.id is the string AuditForm, then you have no choice but to use dynamic property notation on the global window object, or use eval if you didn't declare AuditForm with var on the global scope:

If you declare AuditForm with var on the global scope:

fileIt(window[formID]);

If you don't:

fileIt(eval(formID));

Do note that eval is a very poor option, as if obj.id can be interpreted as other code, e.g. another eval call which will be evaluated, then malicious operations can be performed. Example:

const obj = {
  id: "eval('alert(\"Inside an eval script!\")')"
};

eval(obj.id);
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
  • 2
    Strongly recommend **not** suggesting `eval` to obvious newbies without carefully explaining why not to use it and what to do instead. – T.J. Crowder Apr 30 '19 at 09:10
  • Yes @T.J.Crowder - but I don't believe there's another way to do this if you don't declare the variable with `var` on the global scope without using `eval`. – Jack Bashford Apr 30 '19 at 09:11
  • 1
    @JackBashford I think T.J. Crowder is giving his point with _without carefully explaining why not to use it and what to do instead._ ... Just explain **why** it can be used in this context :P. – briosheje Apr 30 '19 at 09:13
  • AuditForm is an object/class not a function so no need of `eval` so maybe a need of JSON.stringify() or nothing. – AZ_ Apr 30 '19 at 09:21
  • @JackBashford - I usually show them what to do instead, e.g., put the things they want to look up this way in an object as properties, and then access the properties via brackets notation. – T.J. Crowder Apr 30 '19 at 09:24