在为变量赋值之前在 javascript 中声明变量时,是否有类似最佳实践的做法?有时出于范围原因这是必要的,但如果范围不重要怎么办?
// Declare first
(function() {
var foo = 'bar',
a = 500,
b = 300,
c;
// Some things get done here with a and b before c can use them...
c = a * b;
// c is now ready to use...
doSomething(c);
}());
// Declare when needed
(function() {
var foo = 'bar',
a = 500,
b = 300;
// Some things get done here with a and b before c can use them...
var c = a * b;
// c is now ready to use...
doSomething(c);
}());
我还想知道与对象文字类似的最佳实践是什么:
// Add property with null assigned to it
var myObj = {
foo: null,
doSomething: function() {
this.foo = 'bar';
}
};
// Property gets added when value is set
var myObj = {
doSomething: function() {
this.foo = 'bar';
}
};
最佳答案
这主要是风格问题。
As var
声明自动 hoisted up到作用域的顶部,将它们放置在其作用域的顶部是有意义的,这样您可以更接近解释器执行代码的方式阅读代码。
在其作用域顶部声明变量是 Crockford's recommendation 。它确实有道理,因为它消除了一些常见的误解。
例如:
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 0);
}
由于 var
具有函数作用域,因此所有迭代(以及其中的函数)都引用相同的 i
。由于所有三个定时函数都将在循环结束后执行,因此上面的代码片段会记录 3
三次。
现在对于那些具有 block 作用域经验的人来说,上述行为并不是很清楚。重写代码片段:
var i;
for (i = 0; i < 3; i++) {
// ...
}
现在,i
在全局范围内声明,与前面的代码片段完全相同。然而,这个在这一点上更加清楚。
另一个误解:
(function() {
if (true) {
var foo = 1;
} else {
var foo = 1;
}
}());
同样,在 block 作用域语言中,上述内容是完全有效的。但是,由于 var
声明在解析时被提升到当前函数作用域的顶部,因此上面的内容相当于:
(function() {
var foo;
var foo;
if (true) {
foo = 1;
} else {
foo = 1;
}
}());
该变量被声明两次。大多数浏览器只会忽略第二个声明,代码将“工作”,但静态代码分析工具如 JSHint会对你大喊大叫。
您只需使用一个声明即可重写它,并且它是完全有效的:
(function() {
if (true) {
var foo = 1;
} else {
foo = 1;
}
}());
但是像我这样的强制症程序员会觉得它相当难看。再次,在范围顶部声明:
(function() {
var foo;
if (true) {
foo = 1;
} else {
foo = 1;
}
}());
看起来整洁多了。
<小时/>同样,这主要是风格问题。就我个人而言,如果我有一个巨大的函数,我讨厌一直向上滚动只是为了检查变量是否已经声明并将其添加到列表中。在这种情况下,我可能只在函数中间添加几个 var
声明(违背 Crockford 的建议),我个人认为这更易于阅读和维护。
由于这是风格问题,请确保您的代码尽可能最可维护和简洁。
<小时/>另一方面,我承认,就我个人而言,我在第一次使用变量时就开始并主要使用 var
声明。这是该语言的一个方面,您可以毫无问题地使用它。
但我也承认,如果我从一开始就遵循 Crockford 的建议,我就会少很多麻烦(如上面所示的误解),并且会更快地掌握 JavaScript 的函数作用域方面。
<小时/>¹ 请注意,JS 1.7 通过 let
引入了 block 作用域变量,但尚未得到广泛支持。
关于javascript - 声明空 JavaScript 变量的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16912892/