在finally块内进行清理,在try块中进行返回-不好的做法?

时间:2018-07-11 07:06:39

标签: javascript try-finally

我有这段代码可以找出某些文本的宽度:

<form id="uploader">
  <input type="file" required multiple>
  <button type="submit">Submit</button>
</form>

当try块返回某些东西时,最后在内部进行清理是不好的做法吗?它按预期工作;这个问题与function textWidth(text, font) { const span = document.createElement('span') try { span.style.cssText = `position: absolute; opacity: 0; font: ${font || "'Arial'"};` span.innerText = text document.body.appendChild(span) return span.offsetWidth } finally { document.body.removeChild(span) } } 的工作方式无关,我明白了。我只是想知道是否出于某种原因将宽度存储在变量中,进行清理,然后返回变量?

1 个答案:

答案 0 :(得分:3)

  

当try块返回某些内容时,最后在内部进行清理是否是错误的做法?

不,这是完全正常的做法。

执行return span.offsetWidth时,将评估span.offsetWidth的值并将其放在一边,然后运行finally代码,然后返回该值。无需手动进行。您的finally甚至可以包含span = null;,并且不会影响您的返回值,因为此时表达式span.offsetWidth已经被评估 。< / p>

您可以在the spec中看到它:

  

运行时语义:评估

     

ReturnStatement return 表达式;

     
      
  1. exprRef 为评估 Expression 的结果。
  2.   
  3. exprValue 是? GetValue( exprRef )。
  4.   
  5. 如果! GetGeneratorKind()是异步的,将 exprValue 设置为吗? Await( exprValue )。
  6.   
  7. 返回完成{[[[Type]]:返回,[[Value]]: exprValue ,[[Target]]:空}。
  8.   

在该摘录中,值在exprValue中,该值成为完成记录的一部分(这是一种规范机制,不一定是真实的东西);然后运行finally代码,并使用该完成记录来完成该函数(当然,除非finally抛出或发出替代此return的其他return)。 / p>

您还可以观察它:

function example() {
  let foo = () => {
    console.log("foo called");
    return 42;
  };
  try {
    console.log("Doing: return foo();");
    return foo();
  } finally {
    console.log("finally block, doing foo = null");
    foo = null;
  }
}
console.log(example());