本文系统总结了 JavaScript 代码书写的核心规范。内容涵盖通过立即执行函数(IIFE)隔离全局命名空间、在 ES5 严格模式下提升代码健壮性、使用 var 统一变量声明、利用 === 避免类型转换陷阱,以及分号、三元运算符和 DOM 操作等细节优化。旨在帮助开发者编写更安全、高效且易维护的 JavaScript 代码。
全局命名空间与立即执行函数
全局命名空间污染
建议将代码封装在立即执行函数表达式(IIFE)中,从而构建独立的模块作用域。
不推荐的做法
var x = 10,
y = 100;
console.log(window.x + ' ' + window.y);
推荐的做法
;(function(window){
'use strict';
var x = 10,
y = 100;
console.log(window.x + ' ' + window.y);
}(window));
立即执行函数
在立即执行函数内部,若需使用全局变量,应通过参数传递的方式引入。这样在函数体调用时,全局变量即变为局部变量,有助于提升程序运行性能。
此外,应在立即执行函数的形参列表末尾显式添加 undefined 参数。这是因为在 ES3 环境中,undefined 是可读写的。若在全局作用域中修改了 undefined 的值,代码可能无法按预期执行。
同时建议在立即执行函数的开始和结束处都加上分号,以防止在代码合并过程中,因其他代码不规范而干扰自身代码的执行。
不推荐的做法
(function(){
'use strict';
var x = 10,
y = 100,
c,
elem=$('body');
console.log(window.x + ' ' + window.y);
$(document).on('click',function(){
});
if(typeof c==='undefined'){
//你的代码
}
}());
推荐的做法
;(function($,window,document,undefined){
'use strict';
var x = 10,
y = 100,
c,
elem=$('body');
console.log(window.x + ' ' + window.y);
$(document).on('click',function(){
});
if(typeof c==='undefined'){
//你的代码
}
}(jQuery,window,document));
严格模式的应用
严格模式
ECMAScript 5 的严格模式可以在整个脚本或单个方法内启用。它会对不同的 JavaScript 语境执行更严格的错误检查。严格模式还能确保 JavaScript 代码更加健壮,并提升运行速度。
严格模式会禁止使用未来可能引入的保留关键字。
建议在脚本中启用严格模式,最好将其应用于独立的立即执行函数中。避免在脚本第一行直接启用,这可能导致整个脚本都进入严格模式,进而引发第三方类库兼容性问题。
不推荐的做法
'use strict';
(function(){
}());
推荐的做法
(function(){
'use strict';
}());
变量声明与比较规范
变量声明
所有变量声明都应指定 var。若未指定 var,在严格模式下会报错。此外,同一作用域内的变量应尽量使用一个 var 进行声明,多个变量之间用逗号分隔。
不推荐的做法
function myFun(){
x=5;
y=10;
}
不完全推荐的做法
function myFun(){
var x=5;
var y=10;
}
推荐的做法
function myFun(){
var x=5,
y=10;
}
使用带类型判断的比较
应使用 === 精确比较操作符,以避免 JavaScript 强制类型转换带来的困扰。
使用 === 操作符时,比较双方必须具有相同的类型,否则比较无效。
不推荐的做法
(function(w){
'use strict';
w.console.log('0' == 0); // true
w.console.log('' == false); // true
w.console.log('1' == true); // true
w.console.log(null == undefined); // true
var x = {
valueOf: function() {
return 'X';
}
};
w.console.log(x == 'X');//true
}(window.console.log));
推荐的做法
(function(w){
'use strict';
w.console.log('0' === 0); // false
w.console.log('' === false); // false
w.console.log('1' === true); // false
w.console.log(null === undefined); // false
var x = {
valueOf: function() {
return 'X';
}
};
w.console.log(x === 'X');//false
}(window));
逻辑操作与分号使用
变量赋值时的逻辑操作
逻辑运算符 || 和 && 可用于返回布尔值。当操作对象为非布尔类型时,表达式会自左向右进行真假判断,最终返回一个表达式的值。这在变量赋值时可用来简化代码。
不推荐的做法
if(!x) {
if(!y) {
x = 1;
} else {
x = y;
}
}
推荐的做法
x = x || y || 1;
分号
始终使用分号,因为隐式分号插入机制可能引发难以察觉的错误。务必从根源上避免此类问题[1]。
以下示例展示了缺少分号的危害:
// 1.
MyClass.prototype.myMethod = function() {
return 42;
} //这里没有分号
(function() {
})();
//2.
var x = {
'i': 1,
'j': 2
} // 这里没有分号
//我知道这样的代码你可能永远不会写,但是还是举一个例子
[ffVersion, ieVersion][isIE]();
// 3.
var THINGS_TO_EAT = [apples, oysters, sprayOnCheese] // 这里没有分号
-1 == resultOfOperation() || die();
错误结果
1. JavaScript 错误 —— 首先返回 42 的那个 function 被第二个 function 作为参数传入调用,接着数字 42 也被“调用”而导致出错。
2. 八成你会得到 ‘no such property in undefined' 的错误提示,因为在真实环境中的调用是这个样子:xffVersion, ieVersion().
3. die 总是被调用。因为数组减 1 的结果是 NaN,它不等于任何东西(无论 resultOfOperation 是否返回 NaN)。所以最终的结果是 die() 执行完所获得值将赋给 THINGS_TO_EAT。
函数声明与 Eval 使用
八、语句块内的函数声明
切勿在语句块内声明函数,在 ECMAScript 5 的严格模式下,这是不合法的。函数声明应该在作用域的顶层。但在语句块内可将函数申明转化为函数表达式赋值给变量。
不推荐的做法
if (x) {
function foo() {}
}
推荐的做法
if (x) {
var foo = function() {};
}
不要使用 eval 函数
eval() 不但混淆语境还很危险,总会有比这更好、更清晰、更安全的另一种方案来写你的代码,因此尽量不要使用 eval 函数。
数组对象与条件判断
十、数组和对象字面量
1. 用数组和对象字面量来代替数组和对象构造器。数组构造器很容易让人在它的参数上犯错。
不推荐的做法
//数组长度3
var a1 = new Array(x1, x2, x3);
//数组长度2
var a2 = new Array(x1, x2);
//如果x1是一个自然数,那么它的长度将为x1
//如果x1不是一个自然数,那么它的长度将为1
var a3 = new Array(x1);
var a4 = new Array();
正因如此,如果将代码传参从两个变为一个,那数组很有可能发生意料不到的长度变化。为避免此类怪异状况,请总是采用可读的数组字面量。
推荐的做法
var a = [x1, x2, x3];
var a2 = [x1, x2];
var a3 = [x1];
var a4 = [];
2. 对象构造器不会有类似的问题,但是为了可读性和统一性,我们应该使用对象字面量。
不推荐的做法
var o = new Object();
var o2 = new Object();
o2.a = 0;
o2.b = 1;
o2.c = 2;
o2['strange key'] = 3;
推荐的做法
var o = {};
var o2 = {
a: 0,
b: 1,
c: 2,
'strange key': 3
};
三元条件判断(if 的快捷方法)
用三元操作符分配或返回语句。在比较简单的情况下使用,避免在复杂的情况下使用。没人愿意用 10 行三元操作符把自己的脑子绕晕。
不推荐的做法
if(x === 10) {
return 'valid';
} else {
return 'invalid';
}
推荐的做法
return x === 10 ? 'valid' : 'invalid';
循环与 DOM 操作优化
十二、for 循环
使用 for 循环过程中,数组的长度,使用一个变量来接收,这样有利于代码执行效率得到提高,而不是每走一次循环,都得重新计算数组长度
不推荐的做法
for(var i=0;i<arr.length,i++){
}
推荐的做法
for(var i=0,len=arr.length;i<len,i++){
}
十三、重复的 dom 操作
重复的 dom 操作,使用一个变量来进行接收很有必要,而不是频繁的去操作 dom 树,这对性能与代码的整洁及易维护性带来不好的影响
不推荐的做法
$('.myDiv').find('.span1').text('1');
$('.myDiv').find('.span2').text('2');
$('.myDiv').find('.span3').text('3');
$('.myDiv').find('.span4').text('4');
推荐的做法
var mydiv=$('.myDiv');
mydiv.find('.span1').text('1');
mydiv.find('.span2').text('2');
mydiv.find('.span3').text('3');
mydiv.find('.span4').text('4');
在 jquery .end() 可使用的情况下应该优先使用 .end()
推荐的做法
$('.myDiv').find('.span1').text('1')
.end().find('.span2').text('2');
.end().find('.span3').text('3');
.end().find('.span4').text('4');
注释规范
十四、注释规范
在描写注释时,推荐格式化且统一的注释风格,在写注释时尽量描述写代码时的思路,而不是代码做了什么。
不推荐的做法
//获取订单
function getOrderByID(id){
var order;
//...
return order;
}
方法的注释应该统一用块级注释
推荐的做法
/**
* 根据订单id获取订单详细数据
* @param {[number]} id [订单ID]
* @return {[order]} [订单详细信息]
*/
function getOrderByID(id){
var order;
//...
return order;
}
总结
JavaScript 常用代码书写规范总结到这就基本结束了,这篇文章总结的还是很全面的,对大家使用或学些 Javascript 具有一定的参考借鉴价值,希望对大家能有所帮助,如果有疑问大家可以留言交流。