What is the difference between `${variableName}` and {variableName}? - javascript

Are these two syntaxes the same : `${variableName}` and {variableName}

No. First one is JavaScript's template literals
According to the tags of the question I assume the context is about React js. So the second one is use to write javascript within JSX.
For example, If you want to loop through an array in JSX, You can do something like,
<div>
{arr.map(item => <p>{item}</p>)}
</div>
But template literals is feature of pure javascript.
Template literals are string literals allowing embedded expressions.
You can use multi-line strings and string interpolation features with
them.

No, these are not the same. The first one is a template literal, which is used to embed a JavaScript variable inside a string.
For Example
let name = "Rashid";
let age = 20;
console.log(`My Name is ${name} and i'm ${age} years old`);
image example
The second one is to use JavaScript variables in JSX which is mixture of JavaScript and html used in React.
For Example
import "./styles.css";
let name = "Rashid";
let age = 22;
export default function App() {
return (
<div className="App">
<h1>Hello {name}</h1>
<h2>I think you are {age} years old.</h2>
</div>
);
}
image example
CodeSandBox Link

No, they are not the same. One is a javascript template literal, ie: string interpolation and the other is an object or possibly an object decomposition. Or, as pointed out by Dilshan, a javascript expression embedded within JSX. So:
let var1 = 15;
let var2 = {prop: true};
let var3 = 'text';
console.log(`${var1} ${var2} ${var3}`);
outputs the string: 15 [object Object] text
and the following:
let var1 = {prop: true};
let {prop} = var1;
let var2 = {var1};
console.log(var1)
console.log(prop)
console.log(var2)
will produce the output:
{ prop: true }
true
{ var1: { prop: true } }
as the first three statements are equal to:
let var1 = {prop: true};
let prop = var1.prop;
let var2 = {var1: var1};
Or in a JSX file:
import ReactDOMServer from 'react-dom/server';
let var1 = "A string"
let var2 = 34
console.log(
ReactDOMServer.renderToStaticMarkup(
<ul>
<li>{var1}</li>
<li>{var2}</li>
</ul>
)
);
Which Babel will convert to:
"use strict";
var _server = _interopRequireDefault(require("react-dom/server"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var var1 = "A string";
var var2 = 34;
console.log(_server.default.renderToStaticMarkup( /*#__PURE__*/React.createElement("ul", null, /*#__PURE__*/React.createElement("li", null, var1), /*#__PURE__*/React.createElement("li", null, var2))));
And, when run, will output:
<ul>
<li>A string</li>
<li>34</li>
</ul>
Unless of course you meant to type:
`{variableName}`
In which case it's just a regular string without any interpolation. If you printed it out like so:
console.log(`{variableName}`);
Your output would be:
{variableName}

${variableName} Used when concatenating the string:
let my_name = 'abc';
console.log(`my name is ${yourname}. Bye`)
console.log('my name is ' + yourname + '. Bye')

Related

Is it possible to use tagged template literals with template literals saved as constants?

I am working on an application where we have a number of languages. We are not using a package like 'i18n' but instead -- since the number of string literals isn't so large -- using a system like this:
// constants
const GREETING = 'greeting'
// es.js -- a language object
const aLanguageObject = {[GREETING] : '¿Cómo estás?'}
// helper function
const getText(selector) = currentLanguageObject[selector]
// usage file
const greetingPhrase = getText(GREETING);
where currentLanguageObject is one of es.js, en.js, etc, that is, one of the languageObjects already defined (we select based on a process.env value)
We'd like to be able to make use of tagged template literals to interpolate values into these template literals saved as constants.
I've tried to make tagged template literals work with our system like this:
// en.js
const aLanguageObject = {[CONFIRM_NUMBER] : `is the number ${0} correct?`}
and then use tagged templates like this
const theNumber = 12;
const myTag = (strings, numberExp) => `${strings[0]}${theNumber}${strings[1]}`;
const numberConfirmString = myTag`${getText(CONFIRM_NUMBER)})`;
but numberConfirmString is undefined.
Is there a way to "fill in" template literals saved as constants? Any help much appreciated!
The syntax:
const obj = {[key] = value}
Should be:
const obj = {[key]: value}
otherwise, a SyntaxError arises.
Apart of this, I think that something like this should work:
function generaTemplate (strings, ...keys) {
return function(data) {
let temp = strings.slice();
keys.forEach((key, i) => {
temp[i] = temp[i] + data[key];
});
return temp.join('');
}
}
const userTpl = user => generaTemplate`<article>
<p>Name: ${'name'}</p>
<p>Age: ${'age'}</p>
</article>`(user);
const users = [{
name: 'Eric',
age: '10'
}, {
name: 'Rob',
age: '20'
}];
const usersList = users.reduce((acc, user) => {
return acc + userTpl(user);
}, '');
console.log(usersList);
It returns this:
<article>
<p>Name: Eric</p>
<p>Age: 10</p>
</article><article>
<p>Name: Rob</p>
<p>Age: 20</p>
</article>
As alternative, you can also use:
const welcome = param => `Hello, ${param}`;
console.log(welcome('world'));
Output:
Hello, world
Check this: Defer execution for ES6 Template Literals

How to split ``(Backtick string) on each instance of ${variable}

So my question is how i can split the a string with backtick on each instance of variable.
I tried with \${.*?} but this will not work because ${variable} will be replaced by variable values first and than the split function will be executed.
Any idea how to do it ?
let a = 2
let b = 4
let x = `Superman${a}hello${b}one more`.split(/\${.*?}/g)
console.log(x)
On side not: I don't want a solution with wrapping it to " or '.
console.log('`Superman${a}hello${b}one more`'.split(/\${.*?}/g))
After the line executes, there is no way to get the original template string. However, you can use a tag function/tagged template literal to get the parts of the string, including the substitution values:
function Test() {
console.log(arguments)
return arguments.length - 1
}
let a = 2
let b = 4
let c = Test `Superman${a}hello${b}one more`
console.log(`This template string has ${c} substituted values`)
To clarify my comment to the original question here is an example of what the default Template Literal Function does:
function defaultTemplateLiteralFn(strs, ...args) {
return strs.map((str, idx) => str+(args[idx]||'')).join('');
}
const test = "special test";
const a = 10;
const b = 432;
console.log(`This is a ${test}. "${a}+${b}=${a+b}"`)
console.log(defaultTemplateLiteralFn`This is a ${test}. "${a}+${b}=${a+b}"`)
When you use a tagged template (IE: You don't provide a function to handle the template literal) The the language provides a default function that does something similar to what I do in my function defaultTemplateLiteralFn above. It returns the combined parts of the string with the values.
The example function takes each part of the string and puts the appropriate value after the string. If there is no value then it uses a blank string.
One way i have done is using template literal. i have seen this is being used in a in a library called styled-components which allows us to write css with js.
Would love to see other methods if there are any ?
function splitOnVariable(str, age){
// first argument to function will always be array of strings provided in input string.
return str
}
let a = 1;
let b = 2;
console.log(splitOnVariable`hello${a} break me on variable${b} !!!`)

Why does React resolve undefined/boolean/null to string only when they are variables?

I'm trying to wrap my head around JSX.
I've found a very weird behavior.
This is my code:
const name = undefined;
const myFunc = () => undefined;
let template = (
<div>
{myFunc()}
{name}
{undefined}
</div>
);
ReactDOM.render(template, document.querySelector("#root"));
The output is one time:
undefined
Why is the const "name" the only undefined value that is resolved to a string?
What is the difference between this const and the other two expressions?
(Same with Boolean and null.)
Please see my code here: codepen
That's because JSX is syntactic sugar for React.createElement(component, props, ...children)
It will ignore these types (see DOCS):
Boolean
undefined
null
I just realized that this happens only on some editors like codepen because they run the code in the global context and window.name will always be a string.
window.name will convert all values to their string representations by
using the toString method.
If you change the variable to something else, lets say name1 it behaves as expected.
const name1 = undefined;
const myFunc = function(){return undefined};
let template = (
<div>
{name1}
{undefined}
{myFunc()}
</div>
);
By the way, stack-snippets behave the same:
console.log('name is ', name);
const name = undefined;
console.log('and now name is ', name);
const name1 = undefined;
const myFunc = function(){return undefined};
let template = (
<div>
{name}
{name1}
{undefined}
{myFunc()}
</div>
);
ReactDOM.render(template, document.querySelector("#root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Other Editors like codesandbox or jsfiddle will wrap the code in a function, hence there is no conflict with the window.name.
The output here would be empty between your divs. I put this code into jsfiddle to demonstrate:
const name = undefined;
const myFunc = () => undefined;
let template = (
<div>
{myFunc()}
{name}
{undefined}
Hello world
</div>
);
Notice all you can see is the "Hello world" that I added.
It's because the global variable name is the property window.name and will always be a string.
window.name will convert all values to their string representations by using the toString method.
name = undefined
foo = undefined
console.log('`name` is a', typeof name, ', but `foo` is a', typeof foo)
Use a different global variable name, and it should work as expected. But you should typically not use global constants in your templates anyway.

Delayed evaluation for string formatting

I am building up a constants.js file with URLs used in my ReactJS project. These strings include query parameters that can be used with the URL. However, the values used in these strings are only available in a component where the string is used, not in the constants file itself. So for example, I want something like this:
export const BASE_URL = 'https://example.com';
export const FOO_QUERY = '?foo=%s';
where %s is just a placeholder that can be replaced later in a component. (I borrowed printf() syntax from C here for illustration purposes.) What is the correct syntax to do something like this in JavaScript? Is it even possible?
I'd probably use a template literal in a function: The component calls the function with the foo value:
export const fooQuery = foo => `?foo=${foo}`;
Usage:
const query = fooQuery("foo value");
With tagged template literals you could do:
function query(parts, ...pos) {
return apply(...args) {
return parts.map((part, i) => part + args[ pos[i] ]).join("");
}
}
Usable as:
const find = query`?name=${0}&fullname=${0}&age=${1}`;
console.log(find("jonas", 18));
let string = 'bar';
console.log("Foo %s", string);
var teststr = (string) => `Foo ${string}`; //result: Foo bar

Can you evaluate a property name within a JS object? [duplicate]

This question already has answers here:
How to use a variable for a key in a JavaScript object literal?
(16 answers)
Closed 7 years ago.
I know that you can evaluate the value of a property inside of a JS object, like the following:
let object = {
value: 5+5
};
I am wondering if there is any possible way to evaluate the name of an attribute with JS, i.e. achieve the following:
let object;
object[5+5].value = "ten";
As something like:
let object = {
5+5: "ten"
};
Yes in ES2015, no in ES5, but first let's clear one thing up: that's JavaScript, not JSON.
In ES2015 (formerly known as ES6):
var something = "foo";
var object = {
[something]: "bar";
};
alert(object.foo); // "bar"
Inside the [ ] can be any expression you like. The value returned is coerced to a string. That means you can have hours of fun with stuff like
var counter = function() {
var counter = 1;
return function() {
return counter++;
};
};
var object = {
["property" + counter()]: "first property",
["property" + counter()]: "second property"
};
alert(object.property2); // "second property"
JSON is a serialization format inspired by JavaScript object initializer syntax. There is definitely no way to do anything like that in JSON.
Sure. Try this:
'use strict';
let object = {
[5+5]: "ten"
};
console.log(object); // Object {10: "ten"}

Categories