How to pass object as scope to eval? - javascript

I've a javascript object like the following:
var myobj = {
'a': 10, 'b': 20
}
I've a condition stored in a string like the followin:
var c = 'a==10';
I want to evaluate whether the condition in c is true or false. The variables referred in the condition string e.g. a is a member of myobj.
I've tried the following but it didn't help.
eval.call(myobj, 'a==10');

You should really question why you want to use dynamic JS content like that. If the value for c is provided by users then you need to sanitise that input before using it in eval. There are almost always better alternatives.
Therefore the solution I now propose is really enforcing a bad practice -- and not available in strict mode:
var res = eval('with (myobj) ' + c);
Or, depending how you get the info about myobj, this may be easier/more difficult:
with (myobj) var res = eval(c);
So now let's look at some safer ways. Instead of working with such values of c, build a structure of expressions that you allow. For instance:
var c = { prop: "a", operation: "equal", constant: 10 };
... and then do something like this:
var operations = {
equal(a, b) => a == b,
// define other operations here ...
};
function test(obj, c) {
return operations[c.operation](obj[c.prop], c.constant);
}

Here's my attempt at a super hacky solution to this problem using the Function constructor (written in ES2015):
const context = {
a: 10,
b: 20,
};
const expression = 'a==10';
const getAllMatches = (pattern, string) =>
// make sure string is a String, and make sure pattern has the /g flag
String(string).match(new RegExp(pattern, 'g'));
// this pattern is far from robust
const variablePattern = /[a-zA-Z$_][0-9a-zA-Z$_]*/;
const evalWithContext = (context, expression) => {
const variables = getAllMatches(variablePattern, expression);
// function and arguments are keywords, so I use abbreviated names
const func = new Function(...variables, `return (${expression})`);
const args = variables.map((arg) => (Object.hasOwnProperty.call(context, arg)
? context[arg]
: undefined));
return func(...args);
};
console.log(evalWithContext(context, expression));

So dirty :D
var myobj = {
'a': 10,
'b': 20
}
var c = 'a==10';
var res = (function() {
return eval('this.' + c + ';');
}).apply(myobj);
console.log(res);
// or as onliner
var res2 = ((o) => eval('o.' + c)).call(null, myobj);
console.log(res2);

Related

How to convert '${}' string to `${}` string in JavaScript? [duplicate]

I am playing with the new ES6 Template Literals feature and the first thing that came to my head was a String.format for JavaScript so I went about implementing a prototype:
String.prototype.format = function() {
var self = this;
arguments.forEach(function(val,idx) {
self["p"+idx] = val;
});
return this.toString();
};
console.log(`Hello, ${p0}. This is a ${p1}`.format("world", "test"));
ES6Fiddle
However, the Template Literal is evaluated before it's passed to my prototype method. Is there any way I can write the above code to defer the result until after I have dynamically created the elements?
I can see three ways around this:
Use template strings like they were designed to be used, without any format function:
console.log(`Hello, ${"world"}. This is a ${"test"}`);
// might make more sense with variables:
var p0 = "world", p1 = "test";
console.log(`Hello, ${p0}. This is a ${p1}`);
or even function parameters for actual deferral of the evaluation:
const welcome = (p0, p1) => `Hello, ${p0}. This is a ${p1}`;
console.log(welcome("world", "test"));
Don't use a template string, but a plain string literal:
String.prototype.format = function() {
var args = arguments;
return this.replace(/\$\{p(\d)\}/g, function(match, id) {
return args[id];
});
};
console.log("Hello, ${p0}. This is a ${p1}".format("world", "test"));
Use a tagged template literal. Notice that the substitutions will still be evaluated without interception by the handler, so you cannot use identifiers like p0 without having a variable named so. This behavior may change if a different substitution body syntax proposal is accepted (Update: it was not).
function formatter(literals, ...substitutions) {
return {
format: function() {
var out = [];
for(var i=0, k=0; i < literals.length; i++) {
out[k++] = literals[i];
out[k++] = arguments[substitutions[i]];
}
out[k] = literals[i];
return out.join("");
}
};
}
console.log(formatter`Hello, ${0}. This is a ${1}`.format("world", "test"));
// Notice the number literals: ^ ^
Extending #Bergi 's answer, the power of tagged template strings reveals itself when you realize you can return anything as a result, not only plain strings. In his example, the tag constructs and returns an object with a closure and function property format.
In my favorite approach, I return a function value by itself, that you can call later and pass new parameters to fill the template. Like this:
function fmt([fisrt, ...rest], ...tags) {
return values => rest.reduce((acc, curr, i) => {
return acc + values[tags[i]] + curr;
}, fisrt);
}
Or, for the code golfers:
let fmt=([f,...r],...t)=>v=>r.reduce((a,c,i)=>a+v[t[i]]+c,f)
Then you construct your templates and defer the substitutions:
> fmt`Test with ${0}, ${1}, ${2} and ${0} again`(['A', 'B', 'C']);
// 'Test with A, B, C and A again'
> template = fmt`Test with ${'foo'}, ${'bar'}, ${'baz'} and ${'foo'} again`
> template({ foo:'FOO', bar:'BAR' })
// 'Test with FOO, BAR, undefined and FOO again'
Another option, closer to what you wrote, would be to return a object extended from a string, to get duck-typing out of the box and respect interface. An extension to the String.prototype wouldn't work because you'd need the closure of the template tag to resolve the parameters later.
class FormatString extends String {
// Some other custom extensions that don't need the template closure
}
function fmt([fisrt, ...rest], ...tags) {
const str = new FormatString(rest.reduce((acc, curr, i) => `${acc}\${${tags[i]}}${curr}`, fisrt));
str.format = values => rest.reduce((acc, curr, i) => {
return acc + values[tags[i]] + curr;
}, fisrt);
return str;
}
Then, in the call-site:
> console.log(fmt`Hello, ${0}. This is a ${1}.`.format(["world", "test"]));
// Hello, world. This is a test.
> template = fmt`Hello, ${'foo'}. This is a ${'bar'}.`
> console.log(template)
// { [String: 'Hello, ${foo}. This is a ${bar}.'] format: [Function] }
> console.log(template.format({ foo: true, bar: null }))
// Hello, true. This is a null.
You can refer to more information and applications in this other answer.
AFAIS, the useful feature "deferred execution of string templates" is still not available. Using a lambda is an expressive, readable and short solution, however:
var greetingTmpl = (...p)=>`Hello, ${p[0]}. This is a ${p[1]}`;
console.log( greetingTmpl("world","test") );
console.log( greetingTmpl("#CodingIntrigue","try") );
You can inject values into string using below function
let inject = (str, obj) => str.replace(/\${(.*?)}/g, (x,g)=> obj[g]);
let inject = (str, obj) => str.replace(/\${(.*?)}/g, (x,g)=> obj[g]);
// --- Examples ---
// parameters in object
let t1 = 'My name is ${name}, I am ${age}. My brother name is also ${name}.';
let r1 = inject(t1, {name: 'JOHN',age: 23} );
console.log("OBJECT:", r1);
// parameters in array
let t2 = "Today ${0} saw ${2} at shop ${1} times - ${0} was haapy."
let r2 = inject(t2, {...['JOHN', 6, 'SUsAN']} );
console.log("ARRAY :", r2);
I also like the idea of the String.format function, and being able to explicitly define the variables for resolution.
This is what I came up with... basically a String.replace method with a deepObject lookup.
const isUndefined = o => typeof o === 'undefined'
const nvl = (o, valueIfUndefined) => isUndefined(o) ? valueIfUndefined : o
// gets a deep value from an object, given a 'path'.
const getDeepValue = (obj, path) =>
path
.replace(/\[|\]\.?/g, '.')
.split('.')
.filter(s => s)
.reduce((acc, val) => acc && acc[val], obj)
// given a string, resolves all template variables.
const resolveTemplate = (str, variables) => {
return str.replace(/\$\{([^\}]+)\}/g, (m, g1) =>
nvl(getDeepValue(variables, g1), m))
}
// add a 'format' method to the String prototype.
String.prototype.format = function(variables) {
return resolveTemplate(this, variables)
}
// setup variables for resolution...
var variables = {}
variables['top level'] = 'Foo'
variables['deep object'] = {text:'Bar'}
var aGlobalVariable = 'Dog'
// ==> Foo Bar <==
console.log('==> ${top level} ${deep object.text} <=='.format(variables))
// ==> Dog Dog <==
console.log('==> ${aGlobalVariable} ${aGlobalVariable} <=='.format(this))
// ==> ${not an object.text} <==
console.log('==> ${not an object.text} <=='.format(variables))
Alternatively, if you want more than just variable resolution (e.g. the behaviour of template literals), you can use the following.
N.B. eval is considered 'evil' - consider using a safe-eval alternative.
// evalutes with a provided 'this' context.
const evalWithContext = (string, context) => function(s){
return eval(s);
}.call(context, string)
// given a string, resolves all template variables.
const resolveTemplate = function(str, variables) {
return str.replace(/\$\{([^\}]+)\}/g, (m, g1) => evalWithContext(g1, variables))
}
// add a 'format' method to the String prototype.
String.prototype.format = function(variables) {
return resolveTemplate(this, variables)
}
// ==> 5Foobar <==
console.log('==> ${1 + 4 + this.someVal} <=='.format({someVal: 'Foobar'}))
I posted an answer to a similar question that gives two approaches where the execution of the template literal is delayed. When the template literal is in a function, the template literal is only evaluated when the function is called, and it is evaluated using the scope of the function.
https://stackoverflow.com/a/49539260/188963
Although this question is already answered, here I have a simple implementations I use when I load configuration files (the code is typescript, but it is very easy to convert into JS, just remove the typings):
/**
* This approach has many limitations:
* - it does not accept variable names with numbers or other symbols (relatively easy to fix)
* - it does not accept arbitrary expressions (quite difficult to fix)
*/
function deferredTemplateLiteral(template: string, env: { [key: string]: string | undefined }): string {
const varsMatcher = /\${([a-zA-Z_]+)}/
const globalVarsmatcher = /\${[a-zA-Z_]+}/g
const varMatches: string[] = template.match(globalVarsmatcher) ?? []
const templateVarNames = varMatches.map(v => v.match(varsMatcher)?.[1] ?? '')
const templateValues: (string | undefined)[] = templateVarNames.map(v => env[v])
const templateInterpolator = new Function(...[...templateVarNames, `return \`${template}\`;`])
return templateInterpolator(...templateValues)
}
// Usage:
deferredTemplateLiteral("hello ${thing}", {thing: "world"}) === "hello world"
Although it's possible to make this stuff more powerful & flexible, it introduces too much complexity and risk without much benefit.
Here a link to the gist: https://gist.github.com/castarco/94c5385539cf4d7104cc4d3513c14f55
(see #Bergi's very similar answer above)
function interpolate(strings, ...positions) {
var errors = positions.filter(pos=>~~pos!==pos);
if (errors.length) {
throw "Invalid Interpolation Positions: " + errors.join(', ');
}
return function $(...vals) {
var output = '';
for (let i = 0; i < positions.length; i ++) {
output += (strings[i] || '') + (vals[positions[i] - 1] || '');
}
output += strings[strings.length - 1];
return output;
};
}
var iString = interpolate`This is ${1}, which is pretty ${2} and ${3}. Just to reiterate, ${1} is ${2}! (nothing ${0} ${100} here)`;
// Sets iString to an interpolation function
console.log(iString('interpolation', 'cool', 'useful', 'extra'));
// Substitutes the values into the iString and returns:
// 'This is interpolation, which is pretty cool and useful.
// Just to reiterate, interpolation is cool! (nothing here)'
The main difference between this and #Bergi's answer is how errors are handled (silently vs not).
It should be easy enough to expand this idea into a syntax that accepts named arguments:
interpolate`This is ${'foo'}, which is pretty ${'bar'}.`({foo: 'interpolation', bar: 'cool'});
https://github.com/spikesagal/es6interpolate/blob/main/src/interpolate.js

Passing class arguments to a template literal in the class method [duplicate]

I am playing with the new ES6 Template Literals feature and the first thing that came to my head was a String.format for JavaScript so I went about implementing a prototype:
String.prototype.format = function() {
var self = this;
arguments.forEach(function(val,idx) {
self["p"+idx] = val;
});
return this.toString();
};
console.log(`Hello, ${p0}. This is a ${p1}`.format("world", "test"));
ES6Fiddle
However, the Template Literal is evaluated before it's passed to my prototype method. Is there any way I can write the above code to defer the result until after I have dynamically created the elements?
I can see three ways around this:
Use template strings like they were designed to be used, without any format function:
console.log(`Hello, ${"world"}. This is a ${"test"}`);
// might make more sense with variables:
var p0 = "world", p1 = "test";
console.log(`Hello, ${p0}. This is a ${p1}`);
or even function parameters for actual deferral of the evaluation:
const welcome = (p0, p1) => `Hello, ${p0}. This is a ${p1}`;
console.log(welcome("world", "test"));
Don't use a template string, but a plain string literal:
String.prototype.format = function() {
var args = arguments;
return this.replace(/\$\{p(\d)\}/g, function(match, id) {
return args[id];
});
};
console.log("Hello, ${p0}. This is a ${p1}".format("world", "test"));
Use a tagged template literal. Notice that the substitutions will still be evaluated without interception by the handler, so you cannot use identifiers like p0 without having a variable named so. This behavior may change if a different substitution body syntax proposal is accepted (Update: it was not).
function formatter(literals, ...substitutions) {
return {
format: function() {
var out = [];
for(var i=0, k=0; i < literals.length; i++) {
out[k++] = literals[i];
out[k++] = arguments[substitutions[i]];
}
out[k] = literals[i];
return out.join("");
}
};
}
console.log(formatter`Hello, ${0}. This is a ${1}`.format("world", "test"));
// Notice the number literals: ^ ^
Extending #Bergi 's answer, the power of tagged template strings reveals itself when you realize you can return anything as a result, not only plain strings. In his example, the tag constructs and returns an object with a closure and function property format.
In my favorite approach, I return a function value by itself, that you can call later and pass new parameters to fill the template. Like this:
function fmt([fisrt, ...rest], ...tags) {
return values => rest.reduce((acc, curr, i) => {
return acc + values[tags[i]] + curr;
}, fisrt);
}
Or, for the code golfers:
let fmt=([f,...r],...t)=>v=>r.reduce((a,c,i)=>a+v[t[i]]+c,f)
Then you construct your templates and defer the substitutions:
> fmt`Test with ${0}, ${1}, ${2} and ${0} again`(['A', 'B', 'C']);
// 'Test with A, B, C and A again'
> template = fmt`Test with ${'foo'}, ${'bar'}, ${'baz'} and ${'foo'} again`
> template({ foo:'FOO', bar:'BAR' })
// 'Test with FOO, BAR, undefined and FOO again'
Another option, closer to what you wrote, would be to return a object extended from a string, to get duck-typing out of the box and respect interface. An extension to the String.prototype wouldn't work because you'd need the closure of the template tag to resolve the parameters later.
class FormatString extends String {
// Some other custom extensions that don't need the template closure
}
function fmt([fisrt, ...rest], ...tags) {
const str = new FormatString(rest.reduce((acc, curr, i) => `${acc}\${${tags[i]}}${curr}`, fisrt));
str.format = values => rest.reduce((acc, curr, i) => {
return acc + values[tags[i]] + curr;
}, fisrt);
return str;
}
Then, in the call-site:
> console.log(fmt`Hello, ${0}. This is a ${1}.`.format(["world", "test"]));
// Hello, world. This is a test.
> template = fmt`Hello, ${'foo'}. This is a ${'bar'}.`
> console.log(template)
// { [String: 'Hello, ${foo}. This is a ${bar}.'] format: [Function] }
> console.log(template.format({ foo: true, bar: null }))
// Hello, true. This is a null.
You can refer to more information and applications in this other answer.
AFAIS, the useful feature "deferred execution of string templates" is still not available. Using a lambda is an expressive, readable and short solution, however:
var greetingTmpl = (...p)=>`Hello, ${p[0]}. This is a ${p[1]}`;
console.log( greetingTmpl("world","test") );
console.log( greetingTmpl("#CodingIntrigue","try") );
You can inject values into string using below function
let inject = (str, obj) => str.replace(/\${(.*?)}/g, (x,g)=> obj[g]);
let inject = (str, obj) => str.replace(/\${(.*?)}/g, (x,g)=> obj[g]);
// --- Examples ---
// parameters in object
let t1 = 'My name is ${name}, I am ${age}. My brother name is also ${name}.';
let r1 = inject(t1, {name: 'JOHN',age: 23} );
console.log("OBJECT:", r1);
// parameters in array
let t2 = "Today ${0} saw ${2} at shop ${1} times - ${0} was haapy."
let r2 = inject(t2, {...['JOHN', 6, 'SUsAN']} );
console.log("ARRAY :", r2);
I also like the idea of the String.format function, and being able to explicitly define the variables for resolution.
This is what I came up with... basically a String.replace method with a deepObject lookup.
const isUndefined = o => typeof o === 'undefined'
const nvl = (o, valueIfUndefined) => isUndefined(o) ? valueIfUndefined : o
// gets a deep value from an object, given a 'path'.
const getDeepValue = (obj, path) =>
path
.replace(/\[|\]\.?/g, '.')
.split('.')
.filter(s => s)
.reduce((acc, val) => acc && acc[val], obj)
// given a string, resolves all template variables.
const resolveTemplate = (str, variables) => {
return str.replace(/\$\{([^\}]+)\}/g, (m, g1) =>
nvl(getDeepValue(variables, g1), m))
}
// add a 'format' method to the String prototype.
String.prototype.format = function(variables) {
return resolveTemplate(this, variables)
}
// setup variables for resolution...
var variables = {}
variables['top level'] = 'Foo'
variables['deep object'] = {text:'Bar'}
var aGlobalVariable = 'Dog'
// ==> Foo Bar <==
console.log('==> ${top level} ${deep object.text} <=='.format(variables))
// ==> Dog Dog <==
console.log('==> ${aGlobalVariable} ${aGlobalVariable} <=='.format(this))
// ==> ${not an object.text} <==
console.log('==> ${not an object.text} <=='.format(variables))
Alternatively, if you want more than just variable resolution (e.g. the behaviour of template literals), you can use the following.
N.B. eval is considered 'evil' - consider using a safe-eval alternative.
// evalutes with a provided 'this' context.
const evalWithContext = (string, context) => function(s){
return eval(s);
}.call(context, string)
// given a string, resolves all template variables.
const resolveTemplate = function(str, variables) {
return str.replace(/\$\{([^\}]+)\}/g, (m, g1) => evalWithContext(g1, variables))
}
// add a 'format' method to the String prototype.
String.prototype.format = function(variables) {
return resolveTemplate(this, variables)
}
// ==> 5Foobar <==
console.log('==> ${1 + 4 + this.someVal} <=='.format({someVal: 'Foobar'}))
I posted an answer to a similar question that gives two approaches where the execution of the template literal is delayed. When the template literal is in a function, the template literal is only evaluated when the function is called, and it is evaluated using the scope of the function.
https://stackoverflow.com/a/49539260/188963
Although this question is already answered, here I have a simple implementations I use when I load configuration files (the code is typescript, but it is very easy to convert into JS, just remove the typings):
/**
* This approach has many limitations:
* - it does not accept variable names with numbers or other symbols (relatively easy to fix)
* - it does not accept arbitrary expressions (quite difficult to fix)
*/
function deferredTemplateLiteral(template: string, env: { [key: string]: string | undefined }): string {
const varsMatcher = /\${([a-zA-Z_]+)}/
const globalVarsmatcher = /\${[a-zA-Z_]+}/g
const varMatches: string[] = template.match(globalVarsmatcher) ?? []
const templateVarNames = varMatches.map(v => v.match(varsMatcher)?.[1] ?? '')
const templateValues: (string | undefined)[] = templateVarNames.map(v => env[v])
const templateInterpolator = new Function(...[...templateVarNames, `return \`${template}\`;`])
return templateInterpolator(...templateValues)
}
// Usage:
deferredTemplateLiteral("hello ${thing}", {thing: "world"}) === "hello world"
Although it's possible to make this stuff more powerful & flexible, it introduces too much complexity and risk without much benefit.
Here a link to the gist: https://gist.github.com/castarco/94c5385539cf4d7104cc4d3513c14f55
(see #Bergi's very similar answer above)
function interpolate(strings, ...positions) {
var errors = positions.filter(pos=>~~pos!==pos);
if (errors.length) {
throw "Invalid Interpolation Positions: " + errors.join(', ');
}
return function $(...vals) {
var output = '';
for (let i = 0; i < positions.length; i ++) {
output += (strings[i] || '') + (vals[positions[i] - 1] || '');
}
output += strings[strings.length - 1];
return output;
};
}
var iString = interpolate`This is ${1}, which is pretty ${2} and ${3}. Just to reiterate, ${1} is ${2}! (nothing ${0} ${100} here)`;
// Sets iString to an interpolation function
console.log(iString('interpolation', 'cool', 'useful', 'extra'));
// Substitutes the values into the iString and returns:
// 'This is interpolation, which is pretty cool and useful.
// Just to reiterate, interpolation is cool! (nothing here)'
The main difference between this and #Bergi's answer is how errors are handled (silently vs not).
It should be easy enough to expand this idea into a syntax that accepts named arguments:
interpolate`This is ${'foo'}, which is pretty ${'bar'}.`({foo: 'interpolation', bar: 'cool'});
https://github.com/spikesagal/es6interpolate/blob/main/src/interpolate.js

Create a input function for several cases [duplicate]

I am trying to return two values in JavaScript. Is this possible?
var newCodes = function() {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
return dCodes, dCodes2;
};
No, but you could return an array containing your values:
function getValues() {
return [getFirstValue(), getSecondValue()]
}
Then you can access them like so:
const [first, second] = getValues()
This is called destructuring assignment and is supported by every major JS environment. It's equivalent to the following:
const values = getValues()
const first = values[0]
const second = values[1]
You can also return an object if you want to assign a name to each value:
function getValues() {
return {
first: getFirstValue(),
second: getSecondValue(),
}
}
And to access them:
const {first, second} = getValues()
Which is the same as:
const values = getValues()
const first = values.first
const second = values.second
It is highly recommended to return an object instead of an array unless the values make sense as a simple tuple, e.g. a coordinate pair [x, y]. With an array, it's easy to forget which value is which, it's harder to add more values later, and it's marginally more difficult to correctly type with TypeScript or JSDoc.
You can do this from ECMAScript 6 onwards using arrays and "destructuring assignments". Note that these are not available in older Javascript versions (meaning — neither with ECMAScript 3rd nor 5th editions).
It allows you to assign to 1+ variables simultaneously:
var [x, y] = [1, 2];
x; // 1
y; // 2
// or
[x, y] = (function(){ return [3, 4]; })();
x; // 3
y; // 4
You can also use object destructuring combined with property value shorthand to name the return values in an object and pick out the ones you want:
let {baz, foo} = (function(){ return {foo: 3, bar: 500, baz: 40} })();
baz; // 40
foo; // 3
And by the way, don't be fooled by the fact that ECMAScript allows you to return 1, 2, .... What really happens there is not what might seem. An expression in return statement — 1, 2, 3 — is nothing but a comma operator applied to numeric literals (1 , 2, and 3) sequentially, which eventually evaluates to the value of its last expression — 3. That's why return 1, 2, 3 is functionally identical to nothing more but return 3.
return 1, 2, 3;
// becomes
return 2, 3;
// becomes
return 3;
Just return an object literal
function newCodes(){
var dCodes = fg.codecsCodes.rs; // Linked ICDs
var dCodes2 = fg.codecsCodes2.rs; //Linked CPTs
return {
dCodes: dCodes,
dCodes2: dCodes2
};
}
var result = newCodes();
alert(result.dCodes);
alert(result.dCodes2);
Since ES6 you can do this
let newCodes = function() {
const dCodes = fg.codecsCodes.rs
const dCodes2 = fg.codecsCodes2.rs
return {dCodes, dCodes2}
};
let {dCodes, dCodes2} = newCodes()
Return expression {dCodes, dCodes2} is property value shorthand and is equivalent to this {dCodes: dCodes, dCodes2: dCodes2}.
This assignment on last line is called object destructing assignment. It extracts property value of an object and assigns it to variable of same name. If you'd like to assign return values to variables of different name you could do it like this let {dCodes: x, dCodes2: y} = newCodes()
Ecmascript 6 includes "destructuring assignments" (as kangax mentioned) so in all browsers (not just Firefox) you'll be able to capture an array of values without having to make a named array or object for the sole purpose of capturing them.
//so to capture from this function
function myfunction()
{
var n=0;var s=1;var w=2;var e=3;
return [n,s,w,e];
}
//instead of having to make a named array or object like this
var IexistJusttoCapture = new Array();
IexistJusttoCapture = myfunction();
north=IexistJusttoCapture[0];
south=IexistJusttoCapture[1];
west=IexistJusttoCapture[2];
east=IexistJusttoCapture[3];
//you'll be able to just do this
[north, south, west, east] = myfunction();
You can try it out in Firefox already!
Another worth to mention newly introduced (ES6) syntax is use of object creation shorthand in addition to destructing assignment.
function fun1() {
var x = 'a';
var y = 'b';
return { x, y, z: 'c' };
// literally means { x: x, y: y, z: 'c' };
}
var { z, x, y } = fun1(); // order or full presence is not really important
// literally means var r = fun1(), x = r.x, y = r.y, z = r.z;
console.log(x, y, z);
This syntax can be polyfilled with babel or other js polyfiller for older browsers but fortunately now works natively with the recent versions of Chrome and Firefox.
But as making a new object, memory allocation (and eventual gc load) are involved here, don't expect much performance from it. JavaScript is not best language for developing highly optimal things anyways but if that is needed, you can consider putting your result on surrounding object or such techniques which are usually common performance tricks between JavaScript, Java and other languages.
function a(){
var d = 2;
var c = 3;
var f = 4;
return {d: d, c: c, f: f};
}
Then use
const {d, c, f} = a();
In new version:
function a(){
var d = 2;
var c = 3;
var f = 4;
return {d, c, f}
}
A very common way to return multiple values in javascript is using an object literals, so something like:
const myFunction = () => {
const firstName = "Alireza",
familyName = "Dezfoolian",
age = 35;
return { firstName, familyName, age};
}
and get the values like this:
myFunction().firstName; //Alireza
myFunction().familyName; //Dezfoolian
myFunction().age; //age
or even a shorter way:
const {firstName, familyName, age} = myFunction();
and get them individually like:
firstName; //Alireza
familyName; //Dezfoolian
age; //35
Other than returning an array or an object as others have recommended, you can also use a collector function (similar to the one found in The Little Schemer):
function a(collector){
collector(12,13);
}
var x,y;
a(function(a,b){
x=a;
y=b;
});
I made a jsperf test to see which one of the three methods is faster. Array is fastest and collector is slowest.
http://jsperf.com/returning-multiple-values-2
In JS, we can easily return a tuple with an array or object, but do not forget! => JS is a callback oriented language, and there is a little secret here for "returning multiple values" that nobody has yet mentioned, try this:
var newCodes = function() {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
return dCodes, dCodes2;
};
becomes
var newCodes = function(fg, cb) {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
cb(null, dCodes, dCodes2);
};
:)
bam! This is simply another way of solving your problem.
You can also do:
function a(){
var d=2;
var c=3;
var f=4;
return {d:d,c:c,f:f}
}
const {d,c,f} = a()
Adding the missing important parts to make this question a complete resource, as this comes up in search results.
Object Destructuring
In object destructuring, you don't necessarily need to use the same key value as your variable name, you can assign a different variable name by defining it as below:
const newCodes = () => {
let dCodes = fg.codecsCodes.rs;
let dCodes2 = fg.codecsCodes2.rs;
return { dCodes, dCodes2 };
};
//destructuring
let { dCodes: code1, dCodes2: code2 } = newCodes();
//now it can be accessed by code1 & code2
console.log(code1, code2);
Array Destructuring
In array destructuring, you can skip the values you don't need.
const newCodes = () => {
//...
return [ dCodes, dCodes2, dCodes3 ];
};
let [ code1, code2 ] = newCodes(); //first two items
let [ code1, ,code3 ] = newCodes(); //skip middle item, get first & last
let [ ,, code3 ] = newCodes(); //skip first two items, get last
let [ code1, ...rest ] = newCodes(); //first item, and others as an array
It's worth noticing that ...rest should always be at the end as it doesn't make any sense to destruct anything after everything else is aggregated to rest.
I hope this will add some value to this question :)
You can use "Object"
function newCodes(){
var obj= new Object();
obj.dCodes = fg.codecsCodes.rs;
obj.dCodes2 = fg.codecsCodes2.rs;
return obj;
}
All's correct. return logically processes from left to right and returns the last value.
function foo(){
return 1,2,3;
}
>> foo()
>> 3
I would suggest to use the latest destructuring assignment (But make sure it's supported in your environment)
var newCodes = function () {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
return {firstCodes: dCodes, secondCodes: dCodes2};
};
var {firstCodes, secondCodes} = newCodes()
I know of two ways to do this:
1. Return as Array
2. Return as Object
Here's an example I found:
<script>
// Defining function
function divideNumbers(dividend, divisor){
var quotient = dividend / divisor;
var arr = [dividend, divisor, quotient];
return arr;
}
// Store returned value in a variable
var all = divideNumbers(10, 2);
// Displaying individual values
alert(all[0]); // 0utputs: 10
alert(all[1]); // 0utputs: 2
alert(all[2]); // 0utputs: 5
</script>
<script>
// Defining function
function divideNumbers(dividend, divisor){
var quotient = dividend / divisor;
var obj = {
dividend: dividend,
divisor: divisor,
quotient: quotient
};
return obj;
}
// Store returned value in a variable
var all = divideNumbers(10, 2);
// Displaying individual values
alert(all.dividend); // 0utputs: 10
alert(all.divisor); // 0utputs: 2
alert(all.quotient); // 0utputs: 5
</script>
Few Days ago i had the similar requirement of getting multiple return values from a function that i created.
From many return values , i needed it to return only specific value for a given condition and then other return value corresponding to other condition.
Here is the Example of how i did that :
Function:
function myTodayDate(){
var today = new Date();
var day = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
var month = ["January","February","March","April","May","June","July","August","September","October","November","December"];
var myTodayObj =
{
myDate : today.getDate(),
myDay : day[today.getDay()],
myMonth : month[today.getMonth()],
year : today.getFullYear()
}
return myTodayObj;
}
Getting Required return value from object returned by function :
var todayDate = myTodayDate().myDate;
var todayDay = myTodayDate().myDay;
var todayMonth = myTodayDate().myMonth;
var todayYear = myTodayDate().year;
The whole point of answering this question is to share this approach of getting Date in good format. Hope it helped you :)
I am nothing adding new here but another alternate way.
var newCodes = function() {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
let [...val] = [dCodes,dCodes2];
return [...val];
};
Well we can not exactly do what your trying. But something likely to below can be done.
function multiReturnValues(){
return {x:10,y:20};
}
Then when calling the method
const {x,y} = multiReturnValues();
console.log(x) ---> 10
console.log(y) ---> 20
It is possible to return a string with many values and variables using the template literals `${}`
like:
var newCodes = function() {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
return `${dCodes}, ${dCodes2}`;
};
It's short and simple.

Is it true, in an effort to do 'tagged templates', that I cannot pass a variable that returns a template literal as an argument? [duplicate]

I am playing with the new ES6 Template Literals feature and the first thing that came to my head was a String.format for JavaScript so I went about implementing a prototype:
String.prototype.format = function() {
var self = this;
arguments.forEach(function(val,idx) {
self["p"+idx] = val;
});
return this.toString();
};
console.log(`Hello, ${p0}. This is a ${p1}`.format("world", "test"));
ES6Fiddle
However, the Template Literal is evaluated before it's passed to my prototype method. Is there any way I can write the above code to defer the result until after I have dynamically created the elements?
I can see three ways around this:
Use template strings like they were designed to be used, without any format function:
console.log(`Hello, ${"world"}. This is a ${"test"}`);
// might make more sense with variables:
var p0 = "world", p1 = "test";
console.log(`Hello, ${p0}. This is a ${p1}`);
or even function parameters for actual deferral of the evaluation:
const welcome = (p0, p1) => `Hello, ${p0}. This is a ${p1}`;
console.log(welcome("world", "test"));
Don't use a template string, but a plain string literal:
String.prototype.format = function() {
var args = arguments;
return this.replace(/\$\{p(\d)\}/g, function(match, id) {
return args[id];
});
};
console.log("Hello, ${p0}. This is a ${p1}".format("world", "test"));
Use a tagged template literal. Notice that the substitutions will still be evaluated without interception by the handler, so you cannot use identifiers like p0 without having a variable named so. This behavior may change if a different substitution body syntax proposal is accepted (Update: it was not).
function formatter(literals, ...substitutions) {
return {
format: function() {
var out = [];
for(var i=0, k=0; i < literals.length; i++) {
out[k++] = literals[i];
out[k++] = arguments[substitutions[i]];
}
out[k] = literals[i];
return out.join("");
}
};
}
console.log(formatter`Hello, ${0}. This is a ${1}`.format("world", "test"));
// Notice the number literals: ^ ^
Extending #Bergi 's answer, the power of tagged template strings reveals itself when you realize you can return anything as a result, not only plain strings. In his example, the tag constructs and returns an object with a closure and function property format.
In my favorite approach, I return a function value by itself, that you can call later and pass new parameters to fill the template. Like this:
function fmt([fisrt, ...rest], ...tags) {
return values => rest.reduce((acc, curr, i) => {
return acc + values[tags[i]] + curr;
}, fisrt);
}
Or, for the code golfers:
let fmt=([f,...r],...t)=>v=>r.reduce((a,c,i)=>a+v[t[i]]+c,f)
Then you construct your templates and defer the substitutions:
> fmt`Test with ${0}, ${1}, ${2} and ${0} again`(['A', 'B', 'C']);
// 'Test with A, B, C and A again'
> template = fmt`Test with ${'foo'}, ${'bar'}, ${'baz'} and ${'foo'} again`
> template({ foo:'FOO', bar:'BAR' })
// 'Test with FOO, BAR, undefined and FOO again'
Another option, closer to what you wrote, would be to return a object extended from a string, to get duck-typing out of the box and respect interface. An extension to the String.prototype wouldn't work because you'd need the closure of the template tag to resolve the parameters later.
class FormatString extends String {
// Some other custom extensions that don't need the template closure
}
function fmt([fisrt, ...rest], ...tags) {
const str = new FormatString(rest.reduce((acc, curr, i) => `${acc}\${${tags[i]}}${curr}`, fisrt));
str.format = values => rest.reduce((acc, curr, i) => {
return acc + values[tags[i]] + curr;
}, fisrt);
return str;
}
Then, in the call-site:
> console.log(fmt`Hello, ${0}. This is a ${1}.`.format(["world", "test"]));
// Hello, world. This is a test.
> template = fmt`Hello, ${'foo'}. This is a ${'bar'}.`
> console.log(template)
// { [String: 'Hello, ${foo}. This is a ${bar}.'] format: [Function] }
> console.log(template.format({ foo: true, bar: null }))
// Hello, true. This is a null.
You can refer to more information and applications in this other answer.
AFAIS, the useful feature "deferred execution of string templates" is still not available. Using a lambda is an expressive, readable and short solution, however:
var greetingTmpl = (...p)=>`Hello, ${p[0]}. This is a ${p[1]}`;
console.log( greetingTmpl("world","test") );
console.log( greetingTmpl("#CodingIntrigue","try") );
You can inject values into string using below function
let inject = (str, obj) => str.replace(/\${(.*?)}/g, (x,g)=> obj[g]);
let inject = (str, obj) => str.replace(/\${(.*?)}/g, (x,g)=> obj[g]);
// --- Examples ---
// parameters in object
let t1 = 'My name is ${name}, I am ${age}. My brother name is also ${name}.';
let r1 = inject(t1, {name: 'JOHN',age: 23} );
console.log("OBJECT:", r1);
// parameters in array
let t2 = "Today ${0} saw ${2} at shop ${1} times - ${0} was haapy."
let r2 = inject(t2, {...['JOHN', 6, 'SUsAN']} );
console.log("ARRAY :", r2);
I also like the idea of the String.format function, and being able to explicitly define the variables for resolution.
This is what I came up with... basically a String.replace method with a deepObject lookup.
const isUndefined = o => typeof o === 'undefined'
const nvl = (o, valueIfUndefined) => isUndefined(o) ? valueIfUndefined : o
// gets a deep value from an object, given a 'path'.
const getDeepValue = (obj, path) =>
path
.replace(/\[|\]\.?/g, '.')
.split('.')
.filter(s => s)
.reduce((acc, val) => acc && acc[val], obj)
// given a string, resolves all template variables.
const resolveTemplate = (str, variables) => {
return str.replace(/\$\{([^\}]+)\}/g, (m, g1) =>
nvl(getDeepValue(variables, g1), m))
}
// add a 'format' method to the String prototype.
String.prototype.format = function(variables) {
return resolveTemplate(this, variables)
}
// setup variables for resolution...
var variables = {}
variables['top level'] = 'Foo'
variables['deep object'] = {text:'Bar'}
var aGlobalVariable = 'Dog'
// ==> Foo Bar <==
console.log('==> ${top level} ${deep object.text} <=='.format(variables))
// ==> Dog Dog <==
console.log('==> ${aGlobalVariable} ${aGlobalVariable} <=='.format(this))
// ==> ${not an object.text} <==
console.log('==> ${not an object.text} <=='.format(variables))
Alternatively, if you want more than just variable resolution (e.g. the behaviour of template literals), you can use the following.
N.B. eval is considered 'evil' - consider using a safe-eval alternative.
// evalutes with a provided 'this' context.
const evalWithContext = (string, context) => function(s){
return eval(s);
}.call(context, string)
// given a string, resolves all template variables.
const resolveTemplate = function(str, variables) {
return str.replace(/\$\{([^\}]+)\}/g, (m, g1) => evalWithContext(g1, variables))
}
// add a 'format' method to the String prototype.
String.prototype.format = function(variables) {
return resolveTemplate(this, variables)
}
// ==> 5Foobar <==
console.log('==> ${1 + 4 + this.someVal} <=='.format({someVal: 'Foobar'}))
I posted an answer to a similar question that gives two approaches where the execution of the template literal is delayed. When the template literal is in a function, the template literal is only evaluated when the function is called, and it is evaluated using the scope of the function.
https://stackoverflow.com/a/49539260/188963
Although this question is already answered, here I have a simple implementations I use when I load configuration files (the code is typescript, but it is very easy to convert into JS, just remove the typings):
/**
* This approach has many limitations:
* - it does not accept variable names with numbers or other symbols (relatively easy to fix)
* - it does not accept arbitrary expressions (quite difficult to fix)
*/
function deferredTemplateLiteral(template: string, env: { [key: string]: string | undefined }): string {
const varsMatcher = /\${([a-zA-Z_]+)}/
const globalVarsmatcher = /\${[a-zA-Z_]+}/g
const varMatches: string[] = template.match(globalVarsmatcher) ?? []
const templateVarNames = varMatches.map(v => v.match(varsMatcher)?.[1] ?? '')
const templateValues: (string | undefined)[] = templateVarNames.map(v => env[v])
const templateInterpolator = new Function(...[...templateVarNames, `return \`${template}\`;`])
return templateInterpolator(...templateValues)
}
// Usage:
deferredTemplateLiteral("hello ${thing}", {thing: "world"}) === "hello world"
Although it's possible to make this stuff more powerful & flexible, it introduces too much complexity and risk without much benefit.
Here a link to the gist: https://gist.github.com/castarco/94c5385539cf4d7104cc4d3513c14f55
(see #Bergi's very similar answer above)
function interpolate(strings, ...positions) {
var errors = positions.filter(pos=>~~pos!==pos);
if (errors.length) {
throw "Invalid Interpolation Positions: " + errors.join(', ');
}
return function $(...vals) {
var output = '';
for (let i = 0; i < positions.length; i ++) {
output += (strings[i] || '') + (vals[positions[i] - 1] || '');
}
output += strings[strings.length - 1];
return output;
};
}
var iString = interpolate`This is ${1}, which is pretty ${2} and ${3}. Just to reiterate, ${1} is ${2}! (nothing ${0} ${100} here)`;
// Sets iString to an interpolation function
console.log(iString('interpolation', 'cool', 'useful', 'extra'));
// Substitutes the values into the iString and returns:
// 'This is interpolation, which is pretty cool and useful.
// Just to reiterate, interpolation is cool! (nothing here)'
The main difference between this and #Bergi's answer is how errors are handled (silently vs not).
It should be easy enough to expand this idea into a syntax that accepts named arguments:
interpolate`This is ${'foo'}, which is pretty ${'bar'}.`({foo: 'interpolation', bar: 'cool'});
https://github.com/spikesagal/es6interpolate/blob/main/src/interpolate.js

JavaScript variable assignments from tuples

In other languages like Python 2 and Python 3, you can define and assign values to a tuple variable, and retrieve their values like this:
tuple = ("Bob", 24)
name, age = tuple
print(name) #name evaluates to Bob
print(age) #age evaluates to 24
Is there anything similar in JavaScript? Or do I just have to do it the ugly way with an array:
tuple = ["Bob", 24]
name = tuple[0] //name Evaluates to Bob
age = tuple[1] //age Evaluates to 24
Is there a better way to simulate Python tuples in JavaScript 5?
Update: See the answer regarding ES6, which should be favored over CoffeeScript for new projects.
Javascript 1.7 added destructuring assignment which allows you to do essentially what you are after.
function getTuple(){
return ["Bob", 24];
}
var [a, b] = getTuple();
// a === "bob" , b === 24 are both true
You have to do it the ugly way. If you really want something like this, you can check out CoffeeScript, which has that and a whole lot of other features that make it look more like python (sorry for making it sound like an advertisement, but I really like it.)
You can do something similar:
var tuple = Object.freeze({ name:'Bob', age:14 })
and then refer to name and age as attributes
tuple.name
tuple.age
This "tuple" feature it is called destructuring in EcmaScript2015 and is soon to be supported by up to date browsers. For the time being, only Firefox and Chrome support it.
But hey, you can use a transpiler.
The code would look as nice as python:
let tuple = ["Bob", 24]
let [name, age] = tuple
console.log(name)
console.log(age)
A frozen array behaves identically to a python tuple:
const tuple = Object.freeze(["Bob", 24]);
let [name, age]; = tuple
console.debug(name); // "Bob"
console.debug(age); // 24
Be fancy and define a class
class Tuple extends Array {
constructor(...items) {
super(...items);
Object.freeze(this);
}
}
let tuple = new Tuple("Jim", 35);
let [name, age] = tuple;
console.debug(name); // Jim
console.debug(age); // 35
tuple = ["Bob", 24]; // no effect
console.debug(name); // Jim
console.debug(age); // 25
Works today in all the latest browsers.
Tuples aren't supported in JavaScript
If you're looking for an immutable list, Object.freeze() can be used to make an array immutable.
The Object.freeze() method freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed. In essence the object is made effectively immutable. The method returns the object being frozen.
Source: Mozilla Developer Network - Object.freeze()
Assign an array as usual but lock it using 'Object.freeze()
> tuple = Object.freeze(['Bob', 24]);
[ 'Bob', 24 ]
Use the values as you would a regular array (python multi-assignment is not supported)
> name = tuple[0]
'Bob'
> age = tuple[1]
24
Attempt to assign a new value
> tuple[0] = 'Steve'
'Steve'
But the value is not changed
> console.log(tuple)
[ 'Bob', 24 ]
Unfortunately you can't use that tuple assignment syntax in (ECMA|Java)Script.
EDIT: Someone linked to Mozilla/JS 1.7 - this wouldn't work cross-browser but if that is not required then there's your answer.
This is not intended to be actually used in real life, just an interesting exercise. See Why is using the JavaScript eval function a bad idea? for details.
This is the closest you can get without resorting to vendor-specific extensions:
myArray = [1,2,3];
eval(set('a,b,c = myArray'));
Helper function:
function set(code) {
var vars=code.split('=')[0].trim().split(',');
var array=code.split('=')[1].trim();
return 'var '+vars.map(function(x,i){return x+'='+array+'['+i+']'}).join(',');
}
Proof that it works in arbitrary scope:
(function(){
myArray = [4,5,6];
eval(set('x,y,z = myArray'));
console.log(y); // prints 5
})()
eval is not supported in Safari.
As an update to The Minister's answer, you can now do this with es2015:
function Tuple(...args) {
args.forEach((val, idx) =>
Object.defineProperty(this, "item"+idx, { get: () => val })
)
}
var t = new Tuple("a", 123)
console.log(t.item0) // "a"
t.item0 = "b"
console.log(t.item0) // "a"
https://jsbin.com/fubaluwimo/edit?js,console
You can have a tuple type in Javascript as well. Just define it with higher order functions (the academic term is Church encoding):
const Tuple = (...args) => {
const Tuple = f => f(...args);
return Object.freeze(Object.assign(Tuple, args));
};
const get1 = tx => tx((x, y) => x);
const get2 = tx => tx((x, y) => y);
const bimap = f => g => tx => tx((x, y) => Tuple(f(x), g(y)));
const toArray = tx => tx((...args) => args);
// aux functions
const inc = x => x + 1;
const toUpperCase = x => x.toUpperCase();
// mock data
const pair = Tuple(1, "a");
// application
console.assert(get1(pair) === 1);
console.assert(get2(pair) === "a");
const {0:x, 1:y} = pair;
console.log(x, y); // 1 a
console.log(toArray(bimap(inc) (toUpperCase) (pair))); // [2, "A"]
const map = new Map([Tuple(1, "a"), Tuple(2, "b")]);
console.log(map.get(1), map.get(2)); // a b
Please note that Tuple isn't used as a normal constructor. The solution doesn't rely on the prototype system at all, but solely on higher order functions.
What are the advantages of tuples over Arrays used like tuples? Church encoded tuples are immutable by design and thus prevent side effects caused by mutations. This helps to build more robust applications. Additionally, it is easier to reason about code that distinguishes between Arrays as a collection type (e.g. [a]) and tuples as related data of various types (e.g. (a, b)).
Here is a simple Javascript Tuple implementation:
var Tuple = (function () {
function Tuple(Item1, Item2) {
var item1 = Item1;
var item2 = Item2;
Object.defineProperty(this, "Item1", {
get: function() { return item1 }
});
Object.defineProperty(this, "Item2", {
get: function() { return item2 }
});
}
return Tuple;
})();
var tuple = new Tuple("Bob", 25); // Instantiation of a new Tuple
var name = tuple.Item1; // Assignment. name will be "Bob"
tuple.Item1 = "Kirk"; // Will not set it. It's immutable.
This is a 2-tuple, however, you could modify my example to support 3,4,5,6 etc. tuples.
I made a tuple implementation that works quite well. This solution allows for array destructuring, as well as basic type-cheking.
const Tuple = (function() {
function Tuple() {
// Tuple needs at least one element
if (arguments.length < 1) {
throw new Error('Tuple needs at least one element');
}
const args = { ...arguments };
// Define a length property (equal to the number of arguments provided)
Object.defineProperty(this, 'length', {
value: arguments.length,
writable: false
});
// Assign values to enumerable properties
for (let i in args) {
Object.defineProperty(this, i, {
enumerable: true,
get() {
return args[+i];
},
// Checking if the type of the provided value matches that of the existing value
set(value) {
if (typeof value !== typeof args[+i]) {
throw new Error('Cannot assign ' + typeof value + ' on ' + typeof args[+i]);
}
args[+i] = value;
}
});
}
// Implementing iteration with Symbol.iterator (allows for array destructuring as well for...of loops)
this[Symbol.iterator] = function() {
const tuple = this;
return {
current: 0,
last: tuple.length - 1,
next() {
if (this.current <= this.last) {
let val = { done: false, value: tuple[this.current] };
this.current++;
return val;
} else {
return { done: true };
}
}
};
};
// Sealing the object to make sure no more values can be added to tuple
Object.seal(this);
}
// check if provided object is a tuple
Tuple.isTuple = function(obj) {
return obj instanceof Tuple;
};
// Misc. for making the tuple more readable when printing to the console
Tuple.prototype.toString = function() {
const copyThis = { ...this };
const values = Object.values(copyThis);
return `(${values.join(', ')})`;
};
// conctat two instances of Tuple
Tuple.concat = function(obj1, obj2) {
if (!Tuple.isTuple(obj1) || !Tuple.isTuple(obj2)) {
throw new Error('Cannot concat Tuple with ' + typeof (obj1 || obj2));
}
const obj1Copy = { ...obj1 };
const obj2Copy = { ...obj2 };
const obj1Items = Object.values(obj1Copy);
const obj2Items = Object.values(obj2Copy);
return new Tuple(...obj1Items, ...obj2Items);
};
return Tuple;
})();
const SNAKE_COLOR = new Tuple(0, 220, 10);
const [red, green, blue] = SNAKE_COLOR;
console.log(green); // => 220

Categories

Resources