我常常在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
的性能情况。 答案 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() { /* ... */ });
代码看起来不错,但是在循环的每次迭代中,您都会创建一个新的函数副本。
这通常是不合需要的(除非你希望函数在该步骤访问迭代变量的值,假设它是用let
或const
声明的),所以我会使用
function listener() { /* ... */ }
var els = document.getElementsByTagName('div');
for(var i=0; i<els.length; ++i)
els[i].addEventListener('click', listener);