ECMAScript模板文字返回不同的结果

时间:2019-03-06 14:00:47

标签: javascript ecmascript-6

我正在学习ECMAScript2016。我尝试使用模板文字来构建一个简单的功能来计算税款,但是我发现当我使用不同的循环样式时,该功能返回的结果完全不同。

当我使用for循环样式时:

const total = 30
function figureTax(literals) {
  let res = ''
  for ( let i = 0; i < literals.length; ++i) {
    res += literals[i]
    if (i < arguments.length) {
      res += arguments[i]
    }
  }
  // let i = 0
  // while (i < literals.length) {
  //   res += literals[i++]
  //   if (i < arguments.length) {
  //     res += arguments[i]
  //   }
  // }
  return res
}
const res = figureTax`Your tax is (${ total * 0.15 } with tax!)`
console.log(res)

它还给我

  

您的税项是(您的税项是(含税!),含税!)4.5

使用while样式时:

const total = 30
function figureTax(literals) {
  let res = ''
  // for ( let i = 0; i < literals.length; ++i) {
  //   res += literals[i]
  //   if (i < arguments.length) {
  //     res += arguments[i]
  //   }
  // }
  let i = 0
  while (i < literals.length) {
    res += literals[i++]
    if (i < arguments.length) {
      res += arguments[i]
    }
  }
  return res
}
const res = figureTax`Your tax is (${ total * 0.15 } with tax!)`
console.log(res)

它给了我正确的结果:

  

您的税是(含税4.5!)

任何人都可以解释吗?

4 个答案:

答案 0 :(得分:3)

与for或while循环无关。如果使用tag functions,则第一个参数是字符串文字的数组,所有下一个都是插值变量。您使用arguments,它是函数的所有参数。请参见以下代码段:

const total = 30;

function figureTaxWithFor(literals, ...args) {
  
  let res = '';
  
  for ( let i = 0; i < literals.length; ++i) {
  
    res += literals[i];
  
    if (i < args.length) res += args[i];
  }

  return res;
}

function figureTaxWithWhile(literals, ...args) {
  
  let res = '';
  let i = 0;

  while (i < literals.length) {
    
    res += literals[i++];
  
    if (i - 1 < args.length) res += args[i - 1];
  }

  return res;
}

const res = figureTaxWithFor`Your tax is (${ total * 0.15 } with tax!)`;
const res2 = figureTaxWithWhile`Your tax is (${ total * 0.15 } with tax!)`;
console.log(res);
console.log(res2);

答案 1 :(得分:2)

要通过尽可能少地更改代码来回答您的问题,这是因为while循环在访问i之前先增加arguments,但是for循环不是 。如果您按如下方式重写for循环,则它也可以工作:

const total = 30
function figureTax(literals) {
  let res = ''
  for ( let i = 0; i < literals.length;) {
    res += literals[i++]
    if (i < arguments.length) {
      res += arguments[i]
    }
  }
  return res
}
const res = figureTax`Your tax is (${ total * 0.15 } with tax!)`
console.log(res)

答案 2 :(得分:1)

区别来自您在while循环中增加i的位置:

res += literals[i++]

对于您的第一次迭代,这将返回literals[0],但是它将比较1 < arguments.length并添加arguments[1]

但是,在您的for循环中,您是通过++i递增的:

for ( let i = 0; i < literals.length; ++i) {

对于您的第一次迭代,这将返回literals[**1**],并且将比较1 < arguments.length并添加arguments[1]

要修复for循环,请更改为i++并在必要时添加+ 1

const total = 30

function figureTax(literals) {
  let res = ''

  for ( let i = 0; i < literals.length; i++) {
    res += literals[i]

    if ((i + 1) < arguments.length) {
      res += arguments[i + 1]
    }
  }

  return res
}

const res = figureTax`Your tax is (${ total * 0.15 } with tax!)`
console.log(res)
//Your tax is (4.5 with tax!)

有关更多信息,请参见What is the difference between ++i and i++?

答案 3 :(得分:0)

您的问题是,literals的索引与arguments的索引相同,而arguments[0]等于literals时,您也会得到相同的内容。

要克服这个问题,您可以采用rest语法

figureTax(literals, ...params)

并捕获所有参数,并使用相同的索引循环。这是您遇到的最后一个参数的问题。


为什么不简化循环以检查长度相同的文字和参数。

function figureTax(literals) {
    let res = literals[0];
    for (let i = 1; i < literals.length; ++i) {
        res += arguments[i] + literals[i];
    }
    return res;
}

const total = 30
const res = figureTax`Your tax is (${ total * 0.15 } with tax!)`

console.log(res)
console.log(figureTax``);