javascript的使用规范
1 命名规范
1.1 JavaScript文件
JavaScript 程序应独立保存在后缀名为 .js 的文件中。应尽量减少在 HTML 中的JavaScript代码,因为存在与HTML中的JavaScript代码会明显增加文件大小,且不能对其进行缓存和压缩。
filename.js或JavaScript的代码应尽量放到 body 的后面。这样可以减少因为载入脚本而造成其他页面内容载入也被延迟的问题。
1.2 缩进
缩进的单位为四个空格。避免使用 Tab 键来缩进。因为始终没有个统一的 Tab 长短标准。虽然使用空格会增加文件的大小,但在局域网中几乎可以忽略,且在最小化过程中也可被消除掉。
1.3 每行长度
避免每行超过 80 个字符。当一条语句一行写不下时,请考虑折行。在运算符号,最好是逗号后换行。在运算符后换行可以减少因为复制粘贴产生的错误被分号掩盖的几率。
1.4 注释
让注释有意义。重点在解释那些不容易立即明白的逻辑上。不要把读者的时间浪费在阅读类似于:
i = 0; // 让 i 等于 0
使用单行注释。块注释用于注释正式文档和无用代码。
及时地更新注释也很重要。错误的注释会让程序更加难以阅读和理解。
1.5 变量声明
所有的变量必须在使用前通过var进行声明。JavaScript 并不强制必须这么做,但这么做可以让程序易于阅读,且也容易发现那些没声明的变量(它们会被编译成全局变量)。将 var 语句放在函数的首部。最好把每个变量的声明语句单独放到一行,并加上注释说明。
var currentEntry; // 当前选择项
var level; // 缩进程度
var size; // 表格大小
尽量减少全局变量的使用。不要让局部变量覆盖全局变量。
1.6 函数声明
所有的函数在使用前进行声明。 内函数的声明跟在 var 语句的后面。这样可以帮助判断哪些变量是在函数范围内的。
函数名与“(”(左括号)之间不应该有空格。“)”(右括号)与开始程序体的“{”(左大括号)应在同一行。函数程序体应缩进四个空格。“}”(右大括号)与声明函数的那一行代码头部对齐。
function outer(c,d){
var e = c * d;
function inner(a, b){
return (e * a) + b;
}
return inner(0, 1);
}
下面这种书写方式可以在 JavaScript 中正常使用,因为在 JavaScript 中,函数和对象的声明可以放到任何表达式允许的地方。且它让内联函数和混合结构具有最好的可读性。
function getElementsByClassName(className) {
var results = [];
walkTheDOM(document.body, function(node) {
var a; // array of class names
var c = node.className; // the node's classname
var i; // loop counter
// If the node has a class name, then split it into a list of simple names.
// If any of them match the requested name, then append the node to the set of results.
if(c){
a = c.split(' ');
for(i = 0; i < a.length; i += 1){
if (a[i] === className){
results.push(node);
break;
}
}
}
});
return results;
}
如果函数是匿名函数,则在function和 “(”(左括号)之间应有一个空格。如果省略了空格,否则会让人感觉函数名叫作function。
var div.onclick = function(e) {
return false;
};
var that = {
method: function() {
return this.datum;
},
datum: 0
};
尽量不使用全局函数,避免函数名重复。
1.7 命名
变量名应由 26 个大小写字母(A..Z,a..z),10 个数字(0..9),和 “_”(下划线)组成。避免使用国际化字符(如中文),因为它们不是在任何地方都可以被方便的阅读和理解。不要在命名中使用 “$”(美元符号)或者 “/”(反斜杠)。不要把 “_”(下划线)作为变量名的第一个字符。它有时用来表示私有变量,但实际上 JavaScript 并没提供私有变量的功能。如果私有变量很重要,那么使用 私有成员 的形式。应避免使用这种容易让人误解的命名习惯。
大多数的变量名和方法命应以小写字母开头。必须与 new 共同使用的构造函数名应以大写字母开头。当 new 被省略时 JavaScript 不会有任何编译错误或运行错误抛出。忘记加 new 时会导致一些严重的问题(比如被当成一般的函数),所以大写构造函数名是我们来尽量避免这种情况发生的唯一办法。
全局变量应该全部大写。(JavaScript 没有宏或者常量,所以不会因此造成误会)
1.7.1 语句
简单语句
每一行最多只包含一条语句。把 “,” (分号)放到每条简单语句的结尾处。注意一个函数赋值或对象赋值语句也是赋值语句,应该以分号结尾。
如:
var eventHandle = function (){
return “Hello,world!”;
};
var param = {
param1: “param1”,
param2: [1,2,3,4],
parms3: new Date()
};
JavaScript 可以把任何表达式当作一条语句。这很容易隐藏一些错误,特别是误加分号的错误。只有在赋值和调用时,表达式才应被当作一条单独的语句。
复合语句
复合语句是被包含在 “{ }”(大括号)的语句序列。被括起的语句必须多缩进四个空格。“{”(左大括号)应在复合语句其实行的结尾处。“}”(右大括号)应与“{”(左大括号)的那一行的开头对齐。大括号应该在所有复合语句中使用,即使只有一条语句,当它们是控制结构的一部分时,比如一个 if 或者 for 语句。这样做可以避免以后添加语句时造成的错误。
1.7.2 标示
语句标示是可选的,只有以下语句必须被标示:while、do、for、switch。
return 语句
一条有返回值的 return 语句不要使用“( )”(括号)来括住返回值。如果返回表达式,则表达式应与 return 关键字在同一行,以避免误加分号错误。
if 语句
if 语句应如以下格式:
if (condition) {
statements;
}
if (condition) {
statements;
} else {
statements;
}
if (condition) {
statements;
} else if (condition) {
statements;
} else {
statements;
}
for 语句
for 语句应如以下格式:
for (initialization; condition; update) {
statements;
}
while 语句
while 语句应如以下格式:
while (condition) {
statements;
}
do 语句
do 语句应如以下格式:
do {
statements;
} while (condition);
不像别的复合语句,do 语句是以 “;”(分号)结尾。
switch
语句
switch 语句应如以下格式:
switch (expression) {
case expression:
statements;
default:
statements;
}
每个 case 与 switch 对齐。这可避免过分缩进。
每一组 statements(除了default 应以 break,return,或者 throw 结尾),不要让它顺次往下执行。
try 语句
try 语句应如以下格式:
try {
statements;
} catch (variable) {
statements;
}
try {
statements;
} catch (variable) {
statements;
} finally {
statements;
}
continue
语句
避免使用
continue 语句。它很容易使得程序的逻辑过程晦涩难懂。
with 语句
不要使用 with 语句。
空白
用空行来将逻辑相关的代码块分割开可以提高程序的可读性。空格应在以下情况时使用:
跟在“(”(左括号)后面的关键字应被一个空格隔开。如:
while (true) {
函数参数与“(”(左括号)之间不应该有空格。这能帮助区分关键字和函数调用。所有的二元操作符,除了“.”(点) 和“(”(左括号)和 “[”(左方括号)应用空格将其与操作数隔开。
一元操作符与其操作数之间不应有空格,除非操作符是个单词,比如 typeof。
每个在控制部分,比如 for 语句中的 “;”(分号)后须跟一个空格。每个 “,”(逗号)后应跟一个空格。
2 封装技巧
Javascript虽然是一种脚本语言,但是这种基于ECMAScript设计的语言还能巧妙的实现一些面向对象的语言的基本特性,如类,继承,多态等。
2.1 类:静态类和普通类
2.1.1 静态类
我们可以通过一个简单的object对象来模拟一个静态类。如:
//定义静态类
var myStaticClass = {
field1: "field1",
field2: [],
field3: true,
print: function() {
alert(
"field1:" + this.field1 + "\r\n" +
"field2:" + this.field2[0] + "\r\n" +
"filed3:" + this.field3
);
}
};
//访问
myStaticClass.field2.push(1);
myStaticClass.print();
2.1.2 普通类
普通类是通过function来模拟的,我们可以通过new关键字来得到当前类的一个实例,如:
//定义普通类
function MyClass() {
this.field1 = "field1";
this.field2 = [];
var field3 = true; //私用成员
this.print = function() {
//调用类的私有方法
privateMethod();
alert(
"field1:" + this.field1 + "\r\n" +
"field2:" + this.field2[0] + "\r\n" +
"filed3:" + this.field3
);
};
var privateMethod = function() {
//私有方法
alert("I was called!");
};
};
//访问
var myClass1 = new MyClass();
myClass1.field1 = "hello";
myClass1.field2.push(1);
myClass1.print();
区别:静态类和普通类的差别除了声明上和访问上的不同外,普通类还有一个特点就是我们可以定义普通类中的成员的访问级别。而静态类所有的成员都是public的访问级别.
2.2继承
Javascript中的继承是通过他本身的原型机制实现的,我们可以访问对象的prototype属性来获取对象的原型副本来实现继承.Javascript下继承可分为:原型继承和原型子类继承,如:
2.2.1原型继承
//基类
function Foo()
{
this.x = 1;
}
//派生
Foo.prototype.y = 2;
//访问
var obj = new Foo();
document.write('obj.y = ' + obj.y);
2.2.2 原型子类继承
我们创建了一个基类对象的实例,并把它做为我们的类的构造函数的原型对象。这么做,我们所创建的所有的对象,将继承基类对象的所有成员和(方法)。但是要注意,基类的构造函数只会被调用一次.
//基类
function Foo(args)
{
this.x = args;
this.y = true;
this.write = function() {
document.write("x:" + this.x +
"y:" + this.y);
};
}
//派生类
function DeriveClass(args) {
this.x = args;
}
//继承
DeriveClass.prototype = new Foo("x");
DeriveClass.prototype = function() {
document.write("DeriveClass is called:" +
"x:" + this.x +
"y:" + this.y);
};
//访问
var obj = new Foo("hello,world");
var obj1 = new DeriveClass("Hello,test");
obj.write();
obj1.write();
在实际开发中,我们可以通过Object.extend(baseClass, deriveClass)来实现继承.如:
Object.extend(new Foo(),{
write: fucntion() {
alert(“hello,world!”);
}
});
2.3 重载
由于Javscript的方法名如果相同,之上的方法将被覆盖,所以我们只能变相的实现重载.如:
function test(arg1,arg2,arg3){
var method1 = function(arg){
document.write(arg);
};
var method2 = function(arg){
method1(arg);
}
var method3 = function(arg){
method1(arg);
}
if(arg1 && !arg2 && !arg3){
method1(arg1);
}else if(arg1 && arg2 && !arg3){
method2(arg2);
}else if(arg1 && arg2 && arg3){
method3(arg3);
}
}
test(1);
test(1,2);
test(1,2,3);
2.4 模拟的静态类和普通类的使用建议
现在很多domain在编写usercontrol或者Page中的Javascript时,大都是声明了大量的全局变量和全局的函数。这样是很容易导致函数和变量被覆盖或者值改变,而且这种方式并没有达到usercontrol可复用的目的。建议参考下面的方式进行usercontrol和page的Javascript的编码:
UserControl:
<div id="myUserControl_<%= this.ClientID %>">
<table id="gridView">
<tr>
<td>Column1</td>
<td>Column2</td>
<td>Column3</td>
</tr>
</table>
<div>
<input id="btnAdd" type="button" value="添加" />
<input id="btnEdit" type="button" value="修改" />
<input id="btnDelete" type="button" value="删除" />
</div>
</div>
<script>
var MyUserControl = function(id) {
this.id = id;
var grid = $("#gridView_" + id); //声明一个私有的gird对象
var self = this; //声明一个私有的局部自引用对象,方便在闭包调用中使用
this.init = function(args) {
/*
* do something
*/
};
this.setValue = function(data) {
/*
* do something
*/
};
this.getValue = function() {
/*
* do something
*/
};
this.clear = function() {
/*
* do something
*/
clearButtons();
};
var clearButtons = function() { //声明一个私有函数来处理按钮的函数
/*
* do something
*/
};
};
</script>
Page:
<script>
var myPage = {
self: this, //自引用
controls: {}, //页面的用户控件集合
init: function(args) {
//1 初始化用户控件
this.controls["myControl1"] = new MyUserControl("用户控件的客户端ID");
this.controls["myControl1"].init(args);
/*
* do someing
*/
},
setValue: function(data) {
},
getValue: function() {
},
clear: function() {
}
};
$(function() {//初始化页面
myPage.init();
});
</script>
尽量在$(function(){…….})中调用初始化页面的函数,避免在某些情况下页面还没有load完成就初始化页面导致出现的问题。
3 JQuery的使用建议
3.1 尽量使用jquery提供的对dom元素的访问和操作方法
由于采用 jQuery 基础框架,大家操作 DOM 元素时尽量采用 jQuery 操作方法可以规避大多数情况下跨浏览器操作dom元素的问题。
3.2 优先使用 jQuery 扩展函数($.fn.*),并使用 jQuery 连写和 jQuery 选择表达式来减少代码行数。
3.3 尽量避免给一个 DOM 元素绑定多个相同类型的事件处理函数,可以将多个相同类型事件处理函数合并到一个处理函数中,通过数据状态来进行分支处理。
3.4 尽量避免使用toggle事件,通过click事件来替换toggle事件,toggle事件在某些情况下不会被触发。
4 Ajax的使用
4.1 页面初次加载时,尽量在 Web 服务器一次性输出所有相关的数据,只在页面加载完成后,用户进行操作时采用 ajax 进行交互;
4.2 由于同步 AJAX 在 IE 下会产生页面假死的问题,所以建议采用异步 AJAX 而非同步 AJAX;
4.3 尽量减少Ajax请求次数,不当地使用Ajax会影响网站性能;
a、页面在初次加载时,页面一加载完就自动进行 Ajax 来加载一些数据,这种情况存在以下问题:
1)、由于页面加载时要产生更多的请求,因此会影响页面性能;
2)、由于异步加载数据时无法确定加载完成时间,当一些操作 DOM 元素的代码执行时,可以会出现 DOM 元素还未生成的情况,从而导致代码执行错误;
对于此种情况可以通过以下方法来解决:
1)、在 Web 服务器端一次性输出所有相关数据,尽量避免页面一加载完,页面就自动进行 AJAX 请求来加载一些数据;
2)、页面加载完成后,如果需要模拟用户操作来自动查询出一些数据,可以在页面加载时,将查询结果数据以 JSON 字符串格式输出到页面,然后在客户端通过前台 JS 代码来绑定展示这些数据;
b、页面加载完成后,用户在当前页面进行操作时采用 Ajax 进行交互,可以通过批量处理和返回数据集合等方式来减少 Ajax 请求次数;
4.4 AJAX 安全问题
对于一些敏感数据必须要在服务器端进行过滤,避免在客户端才对这些数据进行过滤;比如 Company List 数据、Store User 相关数据等;
对于一些关键的业务逻辑代码也必须放在服务器端处理;
5 另外的建议
5.1 {} 和[]
使用 {} 代替 new Object()。使用 [] 代替 new Array() 。这样便于书写且能提高一点执行效率。
当成员名是一组有序的数字时使用数组来保存数据。当成员名是无规律的字符串或其他时使用对象来保存数据。
5.2 ,(逗号)操作符
避免使用逗号操作符,除非在特定的 for 语句的控制部分。(这不包括那些被用在对象定义,数组定义,var 语句,和参数列表中的逗号分隔符。)
5.3 作用域
在 JavaScript 中块没有域。只有函数有域。不要使用块,除非在复合语句中。
5.4 赋值表达式
避免在 if 和 while 语句的条件部分进行赋值。
if (a = b) {
是一条正确语句? 或者
if (a == b) {
才是对的? 避免这种不容易判断对错的结构。
5.5 === 和 !== 操作符
使用 === 和 !== 操作符会相对好点。== 和 != 操作符会进行类型强制转换。 特别是, 不要将 == 用于与错值比较(false,null,undefined,“”,0,NaN)。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步