0

I'm really new to this and as such my terminology is probably poor, ask me for clarification if you need. Sorry if this is a basic question. Here's an example of my problem:

var post1title = "example title 1";
var post1text = "example text 1";
var post2title = "example title 2";
var post2text = "example text 2";

function update() {
    setText("titleBox", post1title);
    setText("bodyBox", post1text);

My goal is to make the function update() have a parameter that allows the text in a text box to be either, for example, post1title or post2title.

I'd like to do something similar to what you do with strings when variables are involved, as shown here:

console.log("User has set the variable post1title to: " + post1title);
// prints "User has set the variable post1title to: example title 1" to the debug console

It doesn't seem like you can do the same thing when calling variables, though. I've tried doing the same as you would with strings (where "n" is a number 1-2):

var post1title = "example title 1";
var post1text = "example text 1";
var post2title = "example title 2";
var post2text = "example text 2";

function update(n) {
    setText("titleBox", post + n + title);
    setText("bodyBox", post + n + text);

This obviously reads as adding three variables together. Is something like this possible?

yatfiw
  • 17
  • 1
  • you want combine names of variables like this – Maheer Ali Feb 10 '19 at 03:40
  • Why do you need that ? you can have all the values in array or object and pass accordingly. there are some ways to do what you're trying to do 1. using global/windows object, 2. second using plain object and bracket notation 3. using eval. but you should avoid using 1 and 3. and 2 is still ok to use. – Code Maniac Feb 10 '19 at 03:59
  • The question **is** `Is it possible to make part of a variable dependent on the parameter of a function?`, though. Only 1. and 3. achieve something like that. Of course it's better to use an object, but that wasn't the question – P Varga Feb 10 '19 at 04:02
  • Are you trying to set default parameters of the `showText()` function calls? – guest271314 Feb 10 '19 at 04:10
  • 1
    Dynamic variable names in javascript? https://stackoverflow.com/questions/5117127/use-dynamic-variable-names-in-javascript – Olafant Feb 10 '19 at 04:10

4 Answers4

0

You could use an object with bracket notation to do something similar to this. This way your object will hold keys, which point to their associated values.

See example below:

var options = {
  post1title: "example title 1",
  post1text: "example text 1",
  post2title: "example title 2",
  post2text: "example text 2"
}

function update(n) {
  setText("titleBox", options["post"+ n + "title"]);
  setText("bodyBox", options["post" + n + "text"]);
}

function setText(id, txt) {
  document.getElementById(id).textContent = txt;
}

update(1)
<h2 id="titleBox"></h2>
<p id="bodyBox" ></p>

Or, an alternative way would be to use a constructor function like so:

var post1title = "example title 1";
var post1text = "example text 1";
var post2title = "example title 2";
var post2text = "example text 2";

function update(n) {
  setText("titleBox", Function("return post"+ n + "title")());
  setText("bodyBox", Function("return post"+ n + "text")());
}

function setText(id, txt) {
  document.getElementById(id).textContent = txt;
}

update(1);
<h2 id="titleBox"></h2>
<p id="bodyBox" ></p>
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • 2
    For function constructor +1. didn't knew this can be done like this too – Code Maniac Feb 10 '19 at 04:18
  • @CodeManiac thanks, yeah it's similar to `eval`, it just has less overhead and ins't as bad :P – Nick Parsons Feb 10 '19 at 04:19
  • In what way is it less bad? Someone could still call `update(", alert('0wned'), void _")` (Always looking for good reasons not to use `eval`) – P Varga Feb 10 '19 at 04:42
  • @pete One reason that `eval` is slower than using a function constructor. Another is that `eval` has the option to expose the scope in which it was called if malicious code is used, whereas the function constructor will not. Take a look at [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Do_not_ever_use_eval!) from MDN – Nick Parsons Feb 10 '19 at 04:47
  • Even, it seems that create-react-app has ESlint built in to disallow `eval()` – Alvin Theodora Feb 10 '19 at 04:52
  • @NickParsons Actually, [`eval()` is faster](http://jsben.ch/T7SVZ), at least in Chrome 72. Not a reason to use it, but still. What do you mean by "expose the scope in which it was called"? – P Varga Feb 10 '19 at 05:00
  • @AlvinTheodora That's great. It's not a React question though. And I'm not trying to promote `eval()`, it's just that it is the answer to this particular question. – P Varga Feb 10 '19 at 05:02
  • 1
    Added object["property"] access as well to [my microbenchmark](http://jsben.ch/K5WmA). It's faster than both, fortunately – P Varga Feb 10 '19 at 05:29
  • @pete hm, interesting. I was going off what MDN said "eval() is also slower than the alternatives, since it has to invoke the JS interpreter, while many other constructs are optimized by modern JS engines." But it seems that this isn't the case for the function constructor. Yeah, thankfully property access is faster – Nick Parsons Feb 10 '19 at 05:46
  • @NickParsons The JS interpreter has to be involved in case of a Function constructor, too. It might just be that in this case, the string in the `eval` is shorter than in the `Function()` case. It does look like the speed is highly dependent on string length for both `eval` and `Function()` – P Varga Feb 10 '19 at 05:50
  • Did a microbenchmark about this too, [comparing eval() vs Function() performance with short and long strings](http://jsben.ch/qoGUb). Looks like it's not the shorter string that makes `eval()` faster – P Varga Feb 10 '19 at 06:00
  • @NickParsons My other idea is that in the case of Function(), the resulting function needs to be called, which adds some overhead. In any case, quite interesting + surprising results – P Varga Feb 10 '19 at 06:03
  • @pete ah, you might be right about the resulting function needing to be called. Yeah, quite interesting indeed, thanks fro running the tests – Nick Parsons Feb 10 '19 at 06:34
0

It's an anti-pattern to say the least, but if you really want to do this (and you don't, but alas):

function update(n) {
  setText("titleBox", eval("post" + n + "title"));
  ...

...and, It has higher performance than using a Function() constructor. Still, eval() is bad practice.

P Varga
  • 19,174
  • 12
  • 70
  • 108
  • 2
    To the down-voter: Any reason? This actually answers the question and also points out that it's bad practice... – P Varga Feb 10 '19 at 03:53
0

You can store the values as properties of a plain object or Map and use computed property names or bracket notation to get the corresponding value.

You can also adjust the order of the expected parameters.

const o = {
  post1title: "example title 1",
  post1text: "example text 1",
  post2title: "example title 2",
  post2text: "example text 2"
}

function update(p, t, n) {
  console.log(o[p + n + t])
}

update('post', 'title', 1);
guest271314
  • 1
  • 15
  • 104
  • 177
-1

It might be better to convert your variables into an object. This structure simulates the best for real-life data fetched from database for example. And I am using Template Literals inside the console.log for combining string and variables in an easier way

var posts = {   
     "title": {
        "1": "example title 1",
       "2": "example title 2",
      },
    
      "text": {
        "1": "example text 1",
        "2": "example text 2",
      }    
}

function update(part, n) {
  /* setText("titleBox", post1title);
  setText("bodyBox", post1text); */
  console.log(`User has set the variable post${n}${part} to: ${posts[part][n]} `); 
}

update('title', '1')
update('title', '2')
update('text', '1')
update('text', '2')
Alvin Theodora
  • 936
  • 1
  • 11
  • 18