JavaScript中的函数声明中的函数表达式是否有任何优点或缺点?

时间:2016-07-03 21:49:20

标签: javascript

我常常在JavaScript代码中看到类似于以下内容的内容:

var numbers = [4, 9, 16, 25];

numbers.forEach(function(item){
    console.log(item);
})

虽然这可以理解,但您也可以通过以下方式编写代码:

function myFunction(item) {
    console.log(item);
}
numbers.forEach(myFunction);

有时我会看到更复杂的例子。声明的地方  与复杂的程序控制混合,例如:

function readStreamAsJSON(stream, callback) {
  var data = "";
  stream.on("data", function(chunk) {
    data += chunk;
  });
  stream.on("end", function() {
    var result, error;
    try { result = JSON.parse(data); }
    catch (e) { error = e; }
    callback(error, result);
  });
  stream.on("error", function(error) {
    callback(error);
  });
}
// taken from http://eloquentjavascript.net/21_skillsharing.html

除了缩短备用变量之外,以一种将函数控制与如此多的定义混合的方式编写我的JS代码有一个优势吗?

  • 我不确定问题的标题是否合适。还要注意,我意识到这个问题可以作为基于意见的问题而被关闭。但是,我并不关心“第一种方式比另一方式更具可读性”之类的意见。我想知道是否存在技术差异(例如forEach vs for loop的性能情况。

2 个答案:

答案 0 :(得分:2)

我相信你有效地询问是否有任何特殊原因你不能写这个:

function readStreamAsJSON(stream, callback) {
  var data = "";
  stream.on("data", function(chunk) {
    data += chunk;
  });
  stream.on("end", function() {
    var result, error;
    try { result = JSON.parse(data); }
    catch (e) { error = e; }
    callback(error, result);
  });
  stream.on("error", function(error) {
    callback(error);
  });
}

作为

function readStreamAsJSON(stream, callback) {
  function dataHandler(chunk) {
    data += chunk;
  }
  function endHandler() {
    var result, error;
    try { result = JSON.parse(data); }
    catch (e) { error = e; }
    callback(error, result);
  }
  function errorHandler(error) {
    callback(error);
  }
  var data = "";
  stream.on("data", dataHandler);
  stream.on("end", endHandler);
  stream.on("error", errorHandler);
}

,例如,宣布这些功能与使用它们分开。

答案是否定,没有,只要你将它们保持在与我上面相同的范围内。虽然两者之间存在小的技术差异,但它们最终以相同的方式运行。你可以随意写下自己喜欢的内容。

请注意我关于范围的观点。这将 NOT 相同:

// NOT THE SAME, WILL NOT WORK
function streamDataHandler(chunk) {
  data += chunk;
}
function streamEndHandler() {
  var result, error;
  try { result = JSON.parse(data); }
  catch (e) { error = e; }
  callback(error, result);
}
function streamErrorHandler(error) {
  callback(error);
}
function readStreamAsJSON(stream, callback) {
  var data = "";
  stream.on("data", streamDataHandler);
  stream.on("end", streamEndHandler);
  stream.on("error", streamErrorHandler);
}

无效的原因是您只有这些功能的一个版本,并且它们不会关闭传递到data的{​​{1}}和callback

另请注意,函数声明必须位于全局范围或函数的顶层。 ES2015在其他一些地方启用了函数语句(看起来与函数声明相同),但规则很复杂,在JavaScript引擎中也不可靠。我建议坚持使用函数表达式的函数顶层声明,以及其他所有声明。

术语的简要说明:此代码中根本没有函数声明

readStreamAsJSON

这是一个函数表达式。语义是不同的(声明发生在不同的时间,并且有不同的规则)。

答案 1 :(得分:1)

函数声明创建一个变量。这在全球范围内特别相关:



function myFunction() {}
[4, 9, 16, 25].forEach(myFunction);
// ...
console.log(myFunction); // The scope has been polluted




并注意循环中的函数表达式:

var els = document.getElementsByTagName('div');
for(var i=0; i<els.length; ++i)
  els[i].addEventListener('click', function() { /* ... */ });

代码看起来不错,但是在循环的每次迭代中,您都会创建一个新的函数副本。

这通常是不合需要的(除非你希望函数在该步骤访问迭代变量的值,假设它是用letconst声明的),所以我会使用

function listener() { /* ... */ }
var els = document.getElementsByTagName('div');
for(var i=0; i<els.length; ++i)
  els[i].addEventListener('click', listener);