8

Just asking to understand how it works:

function say(something) {
  return something;
}
let name = `Reza`;

console.log(say `My name is`, name, '!');

It returns a very weird output. I think that My name is is a string within an array and everything else is just a string (correct me if I am wrong).

My Question is, what is the point of that and when would it make sense to use a function like that?

Also I would be glad if someone could tell me why My name is ${name} is not working (name returns as an empty string).

PS: I know that could use the function with parentheses and it would work but that's not my question.

Reza Saadati
  • 1,224
  • 13
  • 27

6 Answers6

8

why My name is ${name} is not working (name returns as an empty string).

This is because you have to pull out the value of My name is from the array of string values and return it

Try this:

function say(something) {
   var str0 = something[0]
   return str0;
}
let name = `Reza`;
console.log(say`My name is${name}`, name, '!');  // My name is Reza !

We will receive thing like this:

enter image description here

I would like to point out that the ${name} does not mean anything at all, because inside the tag function, we didn't do anything with it.

This is the result after running your codes on the Chrome devtools:

enter image description here

Let's see how we can explain what is actually going on. Well then, what you're using is called Tagged templates:

A more advanced form of template literals are tagged templates. Tags allow you to parse template literals with a function. The first argument of a tag function contains an array of string values.

That's why we see an array in the result:

For instance, if we run this codes on Chrome devtools:

function say(something) {
    return something;
}
console.log(say`anything`);

On the console tab, we will receive this result:

enter image description here

For more information, you could read it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates

As we can see, the weird raw property, according to MDN - Raw strings, it is:

The special raw property, available on the first function argument of tagged templates, allows you to access the raw strings as they were entered, without processing escape sequences.

For example:

function tag(strings) {
  console.log(strings.raw[0]);
}

tag`string text line 1 \n string text line 2`;
// logs "string text line 1 \n string text line 2" ,
// including the two characters '\' and 'n'

And you are using the console.log() method, according to MDN-Console.log() we have its signature:

Syntax: Console.log()

console.log(obj1 [, obj2, ..., objN]);

console.log(msg [, subst1, ..., substN]);

Parameters

obj1 ... objN

A list of JavaScript objects to output. The string representations of each of these objects are appended together in the order listed and output.

msg

A JavaScript string containing zero or more substitution strings.

subst1 ... substN

JavaScript objects with which to replace substitution strings within msg. This gives you additional control over the format of the output.

In your case, you're passing multiple arguments into the Console.log() method, hence it will work as the document said here: Outputting multiple objects

enter image description here

You Nguyen
  • 9,961
  • 4
  • 26
  • 52
2

say tag is missing the arguments to the placeholders in the template string:

function shout(parts, name/*<--HERE*/) {
  return `${parts[0]}${name}${parts[1]}!!!`;
}

let name = `Reza`;
console.log(shout `My name is ${name}`);

say receives data from the template string as a split string around the placeholders:

[
  "My name is ",
  "!"
] Reza

Look at this example from the MDN Documentation:

function myTag(strings, personExp, ageExp) {
  var str0 = strings[0]; // "That "
  var str1 = strings[1]; // " is a "

  var ageStr;
  if (ageExp > 99){
    ageStr = 'centenarian';
  } else {
    ageStr = 'youngster';
  }

  // We can even return a string built using a template literal
  return `${str0}${personExp}${str1}${ageStr}`;
}

var person = 'Mike';
var age = 28;
var output = myTag`That ${ person } is a ${ age }`;
Rafael
  • 7,605
  • 13
  • 31
  • 46
2

Doing My name is ${name} should work. Its because your passing My name is to the say function as a tagged template literal, which by default passes the arguments as an array

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

jman93
  • 367
  • 3
  • 9
  • Close, the template parts are passed as an array while the template args are passed variadically. – Rafael Sep 30 '18 at 13:00
2

Your tagged template has a missing argument, it should include a strings array argument as first argument.

 function say(strings, something) { 
    return strings[0] + "Mr. " + something +"!"; 
} 

let name = `Reza`; 
console.log(say `My name is ${name}`);    
Calvin
  • 149
  • 4
1

Make it simple

console.log `Hi there`;

why My name is ${name} is not working (name returns as an empty string).

console.log(say `My name is`, name, '!'); /* I don't see `${name}` here */

Also, name was never passed as an argument to say function!

function say(something) {
  return something;
}
let name = `Reza`;
/* say without () */
console.log(say `My name is ${name} !`);

/* say with () */
console.log(say(`My name is ${name} !`));

let who = 'everyone';
console.log `Hello ${who}`; /* note, no -> () */
console.log(`Hello ${who}`);
1

I've spent hours researching documents in order to answer your question. And I'll try my best to explain it simply.

My first answer is, in fact, a text explanation. However, I remember W3Schools once said that:

Examples are better than 1000 words. Examples are often easier to understand than text explanations.

Well then, this answer supplements all explanations with clarifying "Try it Yourself" examples.

There are two concepts in Javascript that involved: the Tagged templates and the Console.log() method.

I'll re-write your codes, breaking them into two parts, like this: (the executed result remains the same).

// part 1
function say(something) {
  return something;
}
let name = `Reza`;
let output = say`My name is`; 
// part 2
console.log(output, name, '!');

Let's see how these two parts related to the concepts of Tagged templates and the Console.log() method, respectively.

First, examine this example:

Example 1:

function say(something) {
   return something;
}
let output = say`My name is`; 
console.log(output)

After running this example, we'll see an array that contains one element which is a string: "My name is"

This is the behavior of the Tagged templates

Before we actually dive into how Tagged templates works, let's take a look at some examples below:

Example 2:

function say(something) {
   return something[0];
}
let output = say`My name is`; 
console.log(output)

After running the example 2, we'll receive a string: "My name is", instead of an array as the example 1 did.

Well then, what if I want to pass a name to it? see this:

Example 3

function say(something, name) {
   return `${something[0]}${name}`;
}
let name = 'Reza';
let output = say`My name is ${name}`; 
console.log(output)

Yay! It works as expected. Well then, what if I want to pass two arguments instead of one? see this:

Example 4

function say(something, name, age) {
    let str0 = something[0];
    let str1 = something[1];
    let str2 = something[2];
    return `${str0}${name}${str1}${age}${str2}`;
}
let name = 'Reza';
let age = 1000;
let output = say`My name is ${name}, I'm ${age} years old!`; 
console.log(output)

Quite clear, right? This is how we use Tagged templates.

The examination of the Tagged templates is done now. Let's see how Console.log() method works.

Example 5

console.log(`My name is `)

We are all familiar with this usage of Console.log() method, passing one argument. Well then, what if I want to pass multiple arguments to it. See this:

Example 6

let name = `Reza`;
console.log(`My name is `, name, '!')

It combined all together into one single output.

Well then, for now, let's go back to your sample:

function say(something) {
  return something;  // the `something` is still an array
}
let name = `Reza`;

console.log(say `My name is`, name, '!');
// the console.log() method will try to combine all these three arguments
// into one single output
// this is why we got the output as an array with a string: "name" and a string: "!"

We could fix it like this:

Example 7

function say(something) {
   return something[0]; 
}
let name = `Reza`;
console.log(say`My name is`, name, '!');

Or like this:

Example 8

function say(something, name) {
   return `${something[0]}${name}`; 
}
let name = `Reza`;
console.log(say`My name is ${name} `, '!'); 

However, let's see this example:

Example 9

function say(something, name) {
  return `${something[0]}${name}`; 
}
let name = `Reza`;
console.log(say`My name is ${name} `, name, '!');

We'll receive My name is Reza Reza !. I believe that, for now, we all understand why we got it.

You Nguyen
  • 9,961
  • 4
  • 26
  • 52