【问题标题】:Function without parentheses returns a weird output [duplicate]没有括号的函数返回一个奇怪的输出[重复]
【发布时间】:2019-03-05 13:11:47
【问题描述】:

只是想了解它是如何工作的:

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

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

它返回一个非常奇怪的输出。我认为My name is 是数组中的一个字符串,其他所有内容都只是一个字符串(如果我错了,请纠正我)。

我的问题是,这样做有什么意义?什么时候使用这样的函数才有意义?

如果有人能告诉我为什么 My name is ${name} 不起作用(name 返回为空字符串),我会很高兴。

PS:我知道可以使用带括号的函数并且它会起作用,但这不是我的问题。

【问题讨论】:

    标签: javascript


    【解决方案1】:

    为什么我的名字是 ${name} 不起作用(名称返回为空 字符串)。

    这是因为你必须从字符串值数组中取出My name is的值并返回

    试试这个:

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

    我们会收到这样的东西:

    我想指出${name} 根本没有任何意义,因为在tag function 内部,我们没有对它做任何事情。

    这是在 Chrome 开发工具上运行代码后的结果:

    让我们看看如何解释实际发生的情况。那么,你使用的是Tagged templates

    模板字面量的更高级形式是标记模板。标签允许您使用函数解析模板文字。标记函数的第一个参数包含一个字符串值数组。

    这就是我们在结果中看到array 的原因:

    例如,如果我们在 Chrome devtools 上运行此代码:

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

    在控制台选项卡上,我们将收到以下结果:

    更多信息,你可以在这里阅读:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates

    我们可以看到,奇怪的raw属性,根据MDN - Raw strings,它是:

    标记模板的第一个函数参数上提供的特殊原始属性允许您在输入原始字符串时访问它们,而无需处理转义序列。

    例如:

    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'
    

    而你使用的是console.log()方法,根据MDN-Console.log()我们有它的签名:

    语法:Console.log()

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

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

    参数

    obj1 ... objN

    要输出的 JavaScript 对象列表。的字符串表示 这些对象中的每一个都按列出的顺序附加在一起,并且 输出。

    msg

    包含零个或多个替换字符串的 JavaScript 字符串。

    subst1 ... substN

    用于替换其中的替换字符串的 JavaScript 对象 味精。这使您可以更好地控制输出格式。

    在您的情况下,您将多个参数传递给 Console.log() 方法,因此它将按照此处文档所述工作:Outputting multiple objects

    【讨论】:

    • 很好的答案。从什么时候开始调用函数时不再需要括号了?
    • @0x499602D2 自 es6(标记模板)
    【解决方案2】:

    执行My name is ${name} 应该可以。这是因为您将 My name is 作为标记模板文字传递给 say 函数,默认情况下将参数作为数组传递

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

    【讨论】:

    • 关闭,模板部分作为数组传递,而模板参数以可变方式传递。
    【解决方案3】:

    say 标记缺少模板字符串中占位符的参数:

    function shout(parts, name/*<--HERE*/) {
      return `${parts[0]}${name}${parts[1]}!!!`;
    }
    
    let name = `Reza`;
    console.log(shout `My name is ${name}`);

    say 从模板字符串接收数据作为占位符周围的拆分字符串:

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

    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 }`;
    

    【讨论】:

      【解决方案4】:

      您的标记模板缺少参数,它应该包含一个字符串数组参数作为第一个参数。

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

      【讨论】:

        【解决方案5】:

        简单一点

        console.log `Hi there`;

        为什么我的名字是 ${name} 不起作用(名称返回为空字符串)。

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

        另外,name 从未作为参数传递给 say 函数!

        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}`);

        【讨论】:

          【解决方案6】:

          为了回答您的问题,我花费了数小时研究文档。我会尽量简单地解释一下。

          事实上,我的第一个答案是文字说明。不过,我记得W3Schools曾经说过:

          示例优于 1000 个单词。示例通常更容易 比文字解释更懂。

          那么,这个答案通过澄清“自己尝试”示例来补充所有解释。

          Javascript 中涉及两个概念:Tagged templatesConsole.log() 方法。

          我将重写你的代码,将它们分成两部分,如下所示:(执行结果保持不变)。

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

          让我们看看这两部分是如何分别与Tagged templatesConsole.log()方法的概念相关的。

          首先,检查这个例子:

          示例 1:

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

          运行此示例后,我们将看到一个 array,其中包含一个元素 string:“我的名字是”

          这是Tagged templates的行为

          在我们真正深入了解Tagged templates 的工作原理之前,让我们看一下下面的一些示例:

          示例 2:

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

          运行示例 2 后,我们将收到 string: "My name is",而不是示例 1 中的 array

          那么,如果我想将name 传递给它怎么办?看到这个:

          示例 3

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

          耶!它按预期工作。那么,如果我想传递两个参数而不是一个呢?看到这个:

          示例 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)

          很清楚,对吧?这就是我们使用Tagged templates的方式。

          Tagged templates 的检查现已完成。让我们看看Console.log() 方法是如何工作的。

          示例 5

          console.log(`My name is `)

          我们都熟悉Console.log() 方法的这种用法,传递一个参数。那么,如果我想向它传递多个参数怎么办。看到这个:

          示例 6

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

          它将所有内容组合成一个输出。

          那么,现在,让我们回到您的示例:

          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: "!"

          我们可以这样修复它:

          示例 7

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

          或者像这样:

          示例 8

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

          但是,让我们看看这个例子:

          示例 9

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

          我们将收到My name is Reza Reza !。我相信,就目前而言,我们都明白我们为什么得到它。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-12-21
            • 1970-01-01
            • 1970-01-01
            • 2016-10-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多