Is there a better way to build strings in JavaScript than doing string concatination?
It would make my code cleaner if I could do something like ruby where you can expand variables in a string instead of doing lots of "foo" + bar + "baz".
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined'
? args[number]
: match
;
});
};
console.log("{0} bar {1}.".format("foo","baz"));
Will produce:
"foo bar baz"
Chris Nielsen has provided a pure-JavaScript solution in this answer:
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g,
function (a, b) {
var r = o[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
}
);
};
alert("I'm {age} years old!".supplant({ age: 29 }));
alert("The {a} says {n}, {n}, {n}!".supplant({ a: 'cow', n: 'moo' }));
You could also use CoffeScript, which is a language that compiles to JavaScript. It supports string interpolation:
author = "Wittgenstein"
quote = "A picture is a fact. -- #{ author }"
sorry guys but all this is not very the ruby way, here is a basic p equivalent, sorry for the eval, that surely can be done better..
if you just want the concatenation, just replace the document.write by return in the first solution
function p(str){
document.write(str.replace(/#{(\w)}/g, function(match, s){return eval(s)})+"<br>");
}
String.prototype.p = function() {
return this.replace(/#{(\w)}/g, function(match, s){return eval(s)})+"<br>";
};
var f="foo", b="bar"
p("#{f} #{b}")
document.write("#{f} #{b}".p());
=> foo bar
=> foo bar
EDIT: i added a prototype version, had some difficulties with that one
var myStr = [];
myStr.push('something')
console.log(myStr.join(""))
If you deal with lots of strings then using an array where you push the string parts and at the end join them (with an empty string as delimiter) seems to be the most efficient across platforms.
"Is there a JavaScript equivalent of rubys “#{}” sequences?"
With respect to an equivalent, no. JavaScript natively does not have string interpolation. Though you could use a function to replicate it to some degree.
pylover's answer will give you something like what you want.
You might also look into CoffeeScript, which is a nice language that compiles to JavaScript and has string interpolation, among other (perhaps too many) features.
It is called syntactic sugar.
var a = 2;
var b = 4;
var c = "together";
var text = `Add ${a*b} elements ${c}.`;
console.log(text)
// "Add 8 elements together." (515,988,604 op/sec)
vs.
var text = "Add" + " " + a*b + " " + "elements" + " " + c + ".";
console.log(text)
// "Add 8 elements together." (511,188,184 op/sec 0.73% slower)
First method is faster and better to read.
Performance tested here: JSPerf string test
Related
I was wondering if it is possible to format numbers in Javascript template strings, for example something like:
var n = 5.1234;
console.log(`This is a number: $.2d{n}`);
// -> 5.12
Or possibly
var n = 5.1234;
console.log(`This is a number: ${n.toString('.2d')}`);
// -> 5.12
That syntax obviously doesn't work, it is just an illustration of the type of thing I'm looking for.
I am aware of tools like sprintf from underscore.string, but this seems like something that JS should be able to do out the box, especially given the power of template strings.
EDIT
As stated above, I am already aware of 3rd party tools (e.g. sprintf) and customised functions to do this. Similar questions (e.g. JavaScript equivalent to printf/String.Format) don't mention template strings at all, probably because they were asked before the ES6 template strings were around. My question is specific to ES6, and is independent of implementation. I am quite happy to accept an answer of "No, this is not possible" if that is case, but what would be great is either info about a new ES6 feature that provides this, or some insight into whether such a feature is on its way.
No, ES6 does not introduce any new number formatting functions, you will have to live with the existing .toExponential(fractionDigits), .toFixed(fractionDigits), .toPrecision(precision), .toString([radix]) and toLocaleString(…) (which has been updated to optionally support the ECMA-402 Standard, though).
Template strings have nothing to do with number formatting, they just desugar to a function call (if tagged) or string concatenation (default).
If those Number methods are not sufficient for you, you will have to roll your own. You can of course write your formatting function as a template string tag if you wish to do so.
You should be able to use the toFixed() method of a number:
var num = 5.1234;
var n = num.toFixed(2);
If you want to use ES6 tag functions here's how such a tag function would look,
function d2(pieces) {
var result = pieces[0];
var substitutions = [].slice.call(arguments, 1);
for (var i = 0; i < substitutions.length; ++i) {
var n = substitutions[i];
if (Number(n) == n) {
result += Number(substitutions[i]).toFixed(2);
} else {
result += substitutions[i];
}
result += pieces[i + 1];
}
return result;
}
which can then be applied to a template string thusly,
d2`${some_float} (you can interpolate as many floats as you want) of ${some_string}`;
that will format the float and leave the string alone.
Here's a fully ES6 version of Filip Allberg's solution above, using ES6 "rest" params. The only thing missing is being able to vary the precision; that could be done by making a factory function. Left as an exercise for the reader.
function d2(strs, ...args) {
var result = strs[0];
for (var i = 0; i < args.length; ++i) {
var n = args[i];
if (Number(n) == n) {
result += Number(args[i]).toFixed(2);
} else {
result += args[i];
}
result += strs[i+1];
}
return result;
}
f=1.2345678;
s="a string";
console.log(d2`template: ${f} ${f*100} and ${s} (literal:${9.0001})`);
While template-string interpolation formatting is not available as a built-in, you can get equivalent behavior with Intl.NumberFormat:
const format = (num, fraction = 2) => new Intl.NumberFormat([], {
minimumFractionDigits: fraction,
maximumFractionDigits: fraction,
}).format(num);
format(5.1234); // -> '5.12'
Note that regardless of your implementation of choice, you might get bitten by rounding errors:
(9.999).toFixed(2) // -> '10.00'
new Intl.NumberFormat([], {
minimumFractionDigits: 2,
maximumFractionDigits: 2, // <- implicit rounding!
}).format(9.999) // -> '10.00'
based on ES6 Tagged Templates (credit to https://stackoverflow.com/a/51680250/711085), this will emulate typical template string syntax in other languages (this is loosely based on python f-strings; I avoid calling it f in case of name overlaps):
Demo:
> F`${(Math.sqrt(2))**2}{.0f}` // normally 2.0000000000000004
"2"
> F`${1/3}{%} ~ ${1/3}{.2%} ~ ${1/3}{d} ~ ${1/3}{.2f} ~ ${1/3}"
"33% ~ 33.33% ~ 0 ~ 0.33 ~ 0.3333333333333333"
> F`${[1/3,1/3]}{.2f} ~ ${{a:1/3, b:1/3}}{.2f} ~ ${"someStr"}`
"[0.33,0.33] ~ {\"a\":\"0.33\",\"b\":\"0.33\"} ~ someStr
Fairly simple code using :
var FORMATTER = function(obj,fmt) {
/* implements things using (Number).toFixed:
${1/3}{.2f} -> 0.33
${1/3}{.0f} -> 1
${1/3}{%} -> 33%
${1/3}{.3%} -> 33.333%
${1/3}{d} -> 0
${{a:1/3,b:1/3}}{.2f} -> {"a":0.33, "b":0.33}
${{a:1/3,b:1/3}}{*:'.2f',b:'%'} -> {"a":0.33, "b":'33%'} //TODO not implemented
${[1/3,1/3]}{.2f} -> [0.33, 0.33]
${someObj} -> if the object/class defines a method [Symbol.FTemplate](){...},
it will be evaluated; alternatively if a method [Symbol.FTemplateKey](key){...}
that can be evaluated to a fmt string; alternatively in the future
once decorators exist, metadata may be appended to object properties to derive
formats //TODO not implemented
*/
try {
let fracDigits=0,percent;
if (fmt===undefined) {
if (typeof obj === 'string')
return obj;
else
return JSON.stringify(obj);
} else if (obj instanceof Array)
return '['+obj.map(x=> FORMATTER(x,fmt))+']'
else if (typeof obj==='object' && obj!==null /*&&!Array.isArray(obj)*/)
return JSON.stringify(Object.fromEntries(Object.entries(obj).map(([k,v])=> [k,FORMATTER(v,fmt)])));
else if (matches = fmt.match(/^\.(\d+)f$/))
[_,fracDigits] = matches;
else if (matches = fmt.match(/^(?:\.(\d+))?(%)$/))
[_,fracDigits,percent] = matches;
else if (matches = fmt.match(/^d$/))
fracDigits = 0;
else
throw 'format not recognized';
if (obj===null)
return 'null';
if (obj===undefined) {
// one might extend the above syntax to
// allow for example for .3f? -> "undefined"|"0.123"
return 'undefined';
}
if (percent)
obj *= 100;
fracDigits = parseFloat(fracDigits);
return obj.toFixed(fracDigits) + (percent? '%':'');
} catch(err) {
throw `error executing F\`$\{${someObj}\}{${fmt}}\` specification: ${err}`
}
}
function F(strs, ...args) {
/* usage: F`Demo: 1+1.5 = ${1+1.5}{.2f}`
--> "Demo: 1+1.5 = 2.50"
*/
let R = strs[0];
args.forEach((arg,i)=> {
let [_,fmt,str] = strs[i+1].match(/(?:\{(.*)(?<!\\)\})?(.*)/);
R += FORMATTER(arg,fmt) + str;
});
return R;
}
sidenote: The core of the code is as follows. The heavy lifting is done by the formatter. The negative lookbehind is somewhat optional, and to let one escape actual curly braces.
let R = strs[0];
args.forEach((arg,i)=> {
let [_,fmt,str] = strs[i+1].match(/(?:\{(.*)(?<!\\)\})?(.*)/);
R += FORMATTER(arg,fmt) + str;
});
You can use es6 tag functions. I don't know ready for use of that.
It might look like this:
num`This is a number: $.2d{n}`
Learn more:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
https://developers.google.com/web/updates/2015/01/ES6-Template-Strings
I'm practicing/studying both JavaScript and Python. I'm wondering if Javascript has the equivalence to this type of coding.
I'm basically trying to get an array from each individual integer from the string for practice purposes. I'm more proficient in Python than JavaScript
Python:
string = '1234-5'
forbidden = '-'
print([int(i) for i in str(string) if i not in forbidden])
Does Javascript have something similar for me to do above?
Update: Array comprehensions were removed from the standard. Quoting MDN:
The array comprehensions syntax is non-standard and removed starting with Firefox 58. For future-facing usages, consider using Array.prototype.map, Array.prototype.filter, arrow functions, and spread syntax.
See this answer for an example with Array.prototype.map:
let emails = people.map(({ email }) => email);
Original answer:
Yes, JavaScript will support array comprehensions in the upcoming EcmaScript version 7.
Here's an example.
var str = "1234-5";
var ignore = "-";
console.log([for (i of str) if (!ignore.includes(i)) i]);
Given the question's Python code
print([int(i) for i in str(string) if i not in forbidden])
this is the most direct translation to JavaScript (ES2015):
const string = '1234-5';
const forbidden = '-';
console.log([...string].filter(c => !forbidden.includes(c)).map(c => parseInt(c)));
// result: [ 1, 2, 3, 4, 5 ]
Here is a comparison of the Python and JavaScript code elements being used:
(Python -> Javascript):
print -> console.log
unpacking string to list -> spread operator
list comprehension 'if' -> Array.filter
list comprehension 'for' -> Array.map
substr in str? -> string.includes
Reading the code, I assume forbidden can have more than 1 character. I'm also assuming the output should be "12345"
var string = "12=34-5";
var forbidden = "=-";
console.log(string.split("").filter(function(str){
return forbidden.indexOf(str) < 0;
}).join(""))
If the output is "1" "2" "3" "4" "5" on separate lines
var string = "12=34-5";
var forbidden = "=-";
string.split("").forEach(function(str){
if (forbidden.indexOf(str) < 0) {
console.log(str);
}
});
Not directly, but it's not hard to replicate.
var string = "1234-5";
var forbidden = "-";
string.split("").filter(function(str){
if(forbidden.indexOf(str) < 0) {
return str;
}
}).forEach(function(letter) { console.log(letter);});
I guess more directly:
for(var i=0 ; i < str.length ; i++) {
if(forbidden.indexOf(str) < 0) {
console.log(str[i]);
}
}
But there's no built in way to filter in your for loop.
You could easily achieve this behavior using an application functor.
Array.prototype.ap = function(xs) {
return this.reduce((acc, f) => acc.concat(xs.map(f)), [])
}
const result = [x => x +1].ap([2])
console.log(result)
JavaScript no longer supports array comprehensions.
I too was looking for the JavaScript equivalent. Mozilla Developer's Network indicates that this functionality is no longer supported.
The preferred syntax is referenced in the aforementioned link.
For "completeness"-sake, here's a shorter regexp version.
var str = "1234-5";
var ignore = "-=";
console.log(str.replace(new RegExp(ignore.split("").join("|")), "").split(""));
EDIT: To make sure that RegExp does not "choke" on special characters, ignore can be implemented as regexp literal, instead of a string:
var str = "1234-5";
var ignore = /[\+=-]/;
console.log(str.replace(ignore, "").split(""));
It does have a poor mans version
const string = '1234-5'
const forbidden = '-'
print([int(i) for i in str(string) if i not in forbidden])
const result = string.split('').filter(char => char !== forbidden);
console.log(result)
In JS you can only iterate over single elements in array, so no extraction of multiple entries at a time like in Python.
For this particular case you should use a RegExp to filter the string though.
You could have a look at CoffeeScript.
CoffeeScript adds missing features to java-script and allows you to write cleaner, more readable code. https://coffeescript.org/#coffeescript-2
You write a .coffee file and the coffeScript-compiler compiles your coffee file into a JavaScript file. Because the translation into JavaScript happens by compiling, the script should not run any slower.
So your code would look like the following in coffee script:
string = '1234-5'
forbidden = '-'
alert(JSON.stringify(+i for i in string when i isnt forbidden))
Honestly, this is even easier to read then the python counterpart. And it compiles quickly to the fallowing JavaScript:
var forbidden, i, string;
string = '1234-5';
forbidden = '-';
alert(JSON.stringify((function() {
var j, len, results;
results = [];
for (j = 0, len = string.length; j < len; j++) {
i = string[j];
if (i !== forbidden) {
results.push(+i);
}
}
return results;
})()));
You don’t even need to install anything. On their website you can play around with it, and it will show you the translated JavaScript code.
Javascript doesn't need list comprehensions because the map and filter functions work better in the language compared to Python.
In Python:
[int(i) for i in '1234-5' if i != '-']
# is equivalent to the ugly
list(map(lambda _: int(_),filter(lambda _: _!='-','1234-5')))
# so we use list comprehensions
In Javascript, to me this is fine once you're familiar with the syntax:
[...'1234-5'].filter(_=> _!='-').map(_=> parseInt(_))
I've been doing JavaScript exercises since i haven't been doing this for too long. Got most of them working but i've been staring blind at this one.
I need to make all lowercase upper & vice versa. I checked the solution and it was helpfull but i'm sure i can get my own code ( which is very different from the answer ) working as well.
Thanks for all bits of help.
function swapCase (str) {
var sen = str;
for ( var i = 0; i < sen.length; i++) {
if (sen.charAt(i) === sen.charAt(i).toLowerCase()) {
sen.charAt(i).toUpperCase();
} else if (sen.charAt(i) === sen.charAt(i).toUpperCase()) {
sen.charAt(i).toLowerCase();
}
} return sen;
}
console.log(swapCase("UPlowUPlow"));
P.s: I am aware that it's not the cleanest bit of code but i've been working on it for a while. :)
toUpperCase and toLowerCase return the modified string, they don't modify it in place. So you'd have to put that value into the string you're processing, e.g.:
sen = sen.substring(0, i - 1) + sen.charAt(i).toUpperCase() + sen.substring(i + 1);
As that's fairly awkward, you'd probably be better off converting the string into an array of single-character strings, processing the array, then combining it again.
You can convert a string into an array of single character strings like this:
theArray = theString.split("");
...then process each entry, in a loop or via Array#map:
theArray[i] = theArray[i].toUpperCase();
...and then convert it back when done:
theString = theArray.join("");
Here's an example using Array#map:
function swapCase (str) {
var theArray = str.split("");
theArray = theArray.map(function(ch) {
var lower = ch.toLowerCase();
return ch === lower ? ch.toUpperCase() : lower;
});
return theArray.join("");
}
var str = "UPlowUPlow";
snippet.log("Before: " + str);
str = swapCase(str);
snippet.log("After: " + str);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Here's the concise version:
function swapCase (str) {
return str.split("").map(function(ch) {
var lower = ch.toLowerCase();
return ch === lower ? ch.toUpperCase() : lower;
}).join("");
}
var str = "UPlowUPlow";
snippet.log("Before: " + str);
str = swapCase(str);
snippet.log("After: " + str);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
sen.charAt(i).toUpperCase() does not change the character at the position. You need to manually update it.
function swapCase (str) {
var sen = str;
var updatedStr = "";
for ( var i = 0; i < sen.length; i++) {
if (sen.charAt(i) === sen.charAt(i).toLowerCase()) {
updatedStr += sen.charAt(i).toUpperCase();
} else if (sen.charAt(i) === sen.charAt(i).toUpperCase()) {
updatedStr += sen.charAt(i).toLowerCase();
}
}
return updatedStr;
}
As a side note, remember that strings are immutable, quoting:
In JavaScript, strings are immutable objects, which means that the
characters within them may not be changed and that any operations on
strings actually create new strings. Strings are assigned by
reference, not by value. In general, when an object is assigned by
reference, a change made to the object through one reference will be
visible through all other references to the object. Because strings
cannot be changed, however, you can have multiple references to a
string object and not worry that the string value will change without
your knowing it
Thanks for the great answers, people!
Thanks to you guys, i "solved" this in seconds while i was working on it for a good amount of time.
I'd love to upvote your answers instead of writing a thank you note, but i'm not yet allowed to do that. So, i'll do it this way.
I am iterating NodeList to get Node data, but while using Node.innerHTML i am getting the tag names in lowercase.
Actual Tags
<Panel><Label>test</Label></Panel>
giving as
<panel><label>test</label></panel>
I need these tags as it is. Is it possible to get it with regular expression? I am using it with dojo (is there any way in dojo?).
var xhrArgs = {
url: "./user/"+Runtime.userName+"/ws/workspace/"+Workbench.getProject()+"/lib/custom/"+(first.type).replace(".","/")+".html",
content: {},
sync:true,
load: function(data){
var test = domConstruct.toDom(data);
dojo.forEach(dojo.query("[id]",test),function(node){
domAttr.remove(node,"id");
});
var childEle = "";
dojo.forEach(test.childNodes,function(node){
if(node.innerHTML){
childEle+=node.innerHTML;
}
});
command.add(new ModifyCommand(newWidget,{},childEle,context));
}
};
You cannot count on .innerHTML preserving the exact nature of your original HTML. In fact, in some browsers, it's significantly different (though generates the same results) with different quotation, case, order of attributes, etc...
It is much better to not rely on the preservation of case and adjust your javascript to deal with uncertain case.
It is certainly possible to use a regular expression to do a case insensitive search (the "i" flag designates its searches as case insensitive), though it is generally much, much better to use direct DOM access/searching rather than innerHTML searching. You'd have to tell us more about what exactly you're trying to do before we could offer some code.
It would take me a bit to figure that out with a regex, but you can use this:
var str = '<panel><label>test</label></panel>';
chars = str.split("");
for (var i = 0; i < chars.length; i++) {
if (chars[i] === '<' || chars[i] === '/') {
chars[i + 1] = chars[i + 1].toUpperCase();
}
}
str = chars.join("");
jsFiddle
I hope it helps.
If you are trying to just capitalise the first character of the tag name, you can use:
var s = 'panel';
s.replace(/(^.)(.*)/,function(m, a, b){return a.toUpperCase() + b.toLowerCase()}); // Panel
Alternatively you can use string manipulation (probably more efficient than a regular expression):
s.charAt(0).toUpperCase() + s.substring(1).toLowerCase(); // Panel
The above will output any input string with the first character in upper case and everything else lower case.
this is not thoroughly tested , and is highly inefficcient, but it worked quite quickly in the console:
(also, it's jquery, but it can be converted to pure javascript/DOM easily)
in jsFiddle
function tagString (element) {
return $(element).
clone().
contents().
remove().
end()[0].
outerHTML.
replace(/(^<\s*\w)|(<\/\s*\w(?=\w*\s*>$))/g,
function (a) {
return a.
toUpperCase();
}).
split(/(?=<\/\s*\w*\s*>$)/);
}
function capContents (element) {
return $(element).
contents().
map(function () {
return this.nodeType === 3 ? $(this).text() : capitalizeHTML(this);
})
}
function capitalizeHTML (selector) {
var e = $(selector).first();
var wrap = tagString(e);
return wrap[0] + capContents(e).toArray().join("") + wrap[1];
}
capitalizeHTML('body');
also, besides being a nice exercise (in my opinion), do you really need to do this?
I'm trying to achieve the following though with my intermediate JavaScript skills I'm not sure if this is possible.
This is related in part to this question.
Now I have 2 arrays
a) Has the various language in (e.g. "en-GB", "fr", "de" etc)
b) Has a suffix of a URL based on the browser language above (e.g. "fr/","de/","uk/")
What I am trying to achieve is:
1) User hits a page, browser detects which browser it is using from the array (a)
2) Depending on what the browser is based on (a), it then searches through (b) and if they match, e.g. if the language is "fr" it will use the suffix "fr/" from the array in (b).
3) It will then add this suffix to a top level domain (which is always constant)
Is this even possible to achieve (I'm sure it is)? Can it be done purely via JavaScript (or JQuery)? How would I go about doing this?
Here's some of the code I have so far:
var IAB_Array = new Array("de-at","nl-be","fr-be","da","de","hu","en-ie","ga","es","fr","it","nl","no","pl","en","en-GB","en-US","en-gb","en-us"); //language array
var IAB_suffix = new Array("at/","be-nl/","be-fr","den/","de/","hu/","ie/","es/","fr/","it/","nl/","nor/","pl/","uk/"); //URL suffix Array
var IAB_lang = "en-GB"; //default language
var IAB_link = "http://www.mysitegoeshere/";
if(navigator.browserLanguage) IAB_lang = navigator.browserLanguage; //change lang if detection supported
if(window.navigator.language) IAB_lang = window.navigator.language; //change lang if detection supported
function IAB_Lang_detect () { //execute search
for (var i=0;i<IAB_Array.length;i++) {
if(IAB_Array[i]==IAB_lang) {
document.write(IAB_Array[i]); //output matched array value
}
}
return false;
}
var IAB_URL = ""+IAB_link+IAB_suffix[1]+""; //this is the resulting URL
document.write(IAB_URL);
IAB_Lang_detect ();
I hope someone can help as I'm a little confused! It's more so the matching the values from the 2 arrays and then subsequently selecting the correct suffix that I'm having trouble with.
Thanks
(function () {
"use strict";
var lang_map = {
"de-at": "at/",
"nl-be": "be-nl/",
"fr-be": "be-fr",
"da": "den/",
"de": "de/",
"hu": "hu/",
"en-ie": "ie/",
"ga": "ie/",
"es": "es/",
"fr": "fr/",
"it": "it/",
"nl": "nl/",
"no": "nor/",
"pl": "pl/",
"en": "uk/",
"en-GB": "uk/",
"en-US": "uk/",
"en-gb": "uk/",
"en-us": "uk/"
},
lang = (navigator && navigator.browserLanguage) || (window.navigator && window.navigator.language) || "en-GB";
window.location = "http://www.mysitegoeshere/" + lang_map[lang];
}());
I'd do it differently and use an object:
var IAB_Object = { "it-It": "it/", "en-Gb": "en/" ....}
if(IAB_Object.hasOwnProperty(IAB_lang)){
//you have a match, the suffix is
var suffix = IAB_Object[IAB_lang];
}else{
//you don't have a match use a standard language
}
I probably wouldn't use arrays for this at all. You can use an object:
var IABInfo = {
"de-at": "at/",
"ln-be": "be-nl/",
// ...and so on
};
Then index directly into that object:
var value = IABInfo[IABLang]; // Where IABLang contains a string, like "de-at"
So:
var suffix = IABInfo[IABLang];
if (suffix) { // Did we have it?
document.write(suffix);
}
This works because all JavaScript objects are free-form key/value maps. Here's a simpler example:
var lifeTheUniverseAndEverything = {
answer: 42,
question: "?"
};
You can look up a property either using dotted notation with a literal, or by using square bracket ([]) notation with a string. So all four of these output exactly the same thing:
// 1. Dotted notation with a literal:
console.log("The answer is " + lifeTheUniverseAndEverything.answer);
// 2. Bracketed notation with a string
console.log("The answer is " + lifeTheUniverseAndEverything["answer"]);
// 3. The string needn't be a literal, it can come from a variable...
var name = "answer";
console.log("The answer is " + lifeTheUniverseAndEverything[name]);
// 4. ...or indeed any expression:
console.log("The answer is " + lifeTheUniverseAndEverything["a" + "n" + "swer"]);
So by making your IAB info a map in an object literal, you can make it much easier to look things up: Just use bracketed notation with the desired language code.