# Javascript编码规范
# 变量命名
- 标准变量采用驼峰式命名(除了对象的属性外,主要是考虑到cgi返回的数据)
- 'ID'在变量名中全大写
- 'URL'在变量名中全大写
- 常量全大写,用下划线连接
- 构造函数,大写第一个字母
let thisIsMyName;
let goodID;
let reportURL;
let AndroidVersion;
let iOSVersion;
const MAX_COUNT = 10;
function Person(name) {
this.name = name;
}
# 变量声明
一个函数作用域中所有的变量声明提到函数首部,除了for (...)里面使用的一次性变量。 let的数量不做限制,但要统一,一行定义一个变量。
// not good
function doSomethingWithItems(items) {
let a,
b;
let value = 10;
let result = value + 10;
for (let i = 0, len = items.length; i < len; i++) {
result += 10;
}
}
// good
function doSomethingWithItems(items) {
let a;
let b;
let value = 10;
let result = value + 10;
for (let i = 0, len = items.length; i < len; i++) {
result += 10;
}
}
# localStorage
由于Safari的隐身模式下本地存储会被禁用,如果你尝试往localStorage写数据的话,会报超出使用限制的错误:QuotaExceededError (DOM Exception 22): The quota has been exceeded.而Chrome的隐身窗口不会禁用。而使用Safari的用户可能会开隐身窗口,特别是手机上的。这样就导致代码抛异常了,所以为了兼容Safari,不能直接使用localStorage,要做个兼容:
Data.hasLocalStorage = true;
try{
window.localStorage.trySetData = 1;
}catch(e){
Data.hasLocalStorage = false;
}
setLocalData: function(key, value){
if(Data.hasLocalStorage){
window.localStorage[key] = value;
}
else{
util.setCookie("_LOCAL_DATA_" + key, value, 1000);
}
},
getLocalData: function(key){
if(Data.hasLocalStorage){
return window.localStorage[key];
}
else{
return util.getCookie("_LOCAL_DATA_" + key);
}
}
上面代码做了个兼容,如果不支持localStorage就使用cookie。要注意cookie一个域名最多只能有4kB,50个key,而本地存储限制为5Mb.
# 常用属性缓存
如下代码,频繁地使用了window.location这个属性
let webLink = window.location.protocol + window.location.hostname;
if(openType === "needtoTouch"){
webLink += "/admin/lead/list/page" +
window.location.search.replace(/openType=needToTouch(&?)/, "") +
window.location.hash;
}
可以先把它缓存一下,加快变量作用域查找
let location = window.location;
let webLink = location.protocol + location.hostname;
if(openType === "needtoTouch"){
webLink += "/admin/lead/list/page" +
location.search.replace(/openType=needToTouch(&?)/, "") +
location.hash;
}
当把location变成一个局部变量之后,它的查找时间将明显快于全局变量。
# 三元运算
禁止嵌套
# null
- 适用场景:
- 初始化一个将来可能被赋值为对象的变量
- 与已经初始化的变量做比较
- 作为一个参数为对象的函数的调用传参
- 作为一个返回对象的函数的返回值
- 不适用场景:
- 不要用null来判断函数调用时有无传参
- 不要与未初始化的变量做比较
// not good
function test(a, b) {
if (b === null) {
// not mean b is not supply
...
}
}
let a;
if (a === null) {
...
}
// good
let a = null;
if (a === null) {
...
}
# undefined
- 永远不要直接使用undefined进行变量判断;
- 使用typeof和字符串'undefined'对变量进行判断。
// not good
if (person === undefined) {
...
}
// good
if (typeof person === 'undefined') {
...
}
# jshint
用'===', '!=='代替'==', '!=';
for-in里一定要有hasOwnProperty的判断;
不要在内置对象的原型上添加方法,如Array, Date;
不要在内层作用域的代码里声明了变量,之后却访问到了外层作用域的同名变量;
变量不要先使用后声明;
不要在一句代码中单单使用构造函数,记得将其赋值给某个变量;
不要在同个作用域下声明同名变量;
不要在一些不需要的地方加括号,例:delete(a.b);
不要使用未声明的变量(全局变量需要加到.jshintrc文件的globals属性里面);
不要声明了变量却不使用;
不要在应该做比较的地方做赋值;
debugger不要出现在提交的代码里;
数组中不要存在空元素;
不要在循环内部声明函数;
不要像这样使用构造函数,例:new function () { ... }, new Object;
// not good
if (a == 1) {
a++;
}
// good
if (a === 1) {
a++;
}
// good
for (key in obj) {
if (obj.hasOwnProperty(key)) {
// be sure that obj[key] belongs to the object and was not inherited
console.log(obj[key]);
}
}
// not good
Array.prototype.count = function(value) {
return 4;
};
// not good
var x = 1;
function test() {
if (true) {
var x = 0;
}
x += 1;
}
// not good
function test() {
console.log(x);
var x = 1;
}
// not good
new Person();
// good
const person = new Person();
// not good
delete(obj.attr);
// good
delete obj.attr;
// not good
if (a = 10) {
a++;
}
// not good
var a = [1, , , 2, 3];
// not good
var nums = [];
for (var i = 0; i < 10; i++) {
(function(i) {
nums[i] = function(j) {
return i + j;
};
}(i));
}
// not good
var singleton = new function() {
var privateVar;
this.publicMethod = function() {
privateVar = 1;
};
this.publicMethod2 = function() {
privateVar = 2;
};
};
# 分号
JS里面的表达式是可以不用分号结尾,例如Zepto的源码几乎没看到一个分号,但是我们还是提倡要每个句子后面都要加上分号,这样不容易出错。 在低版本浏览器(如: IE)中如果不加分号可能会报错。
# 括号
下列关键字后必须有大括号(即使代码块的内容只有一行):if, else, for, while, do, switch, try, catch, finally, with。
// not good
if (condition)
doSomething();
// good
if (condition) {
doSomething();
}
# 使用简便的转换
把字符串转整型可以使用+号
let maxPrice = +form.maxPrice.value; +号相当于Number let maxPrice = Number(form.maxPrice.value);
parseInt和Number有一个很大的区别是parseInt("10px")结果为10,而Number(“10px”)是NaN。
把小数去掉尾数转成整型,可以使用 >> 0如果计算某个数字在第几排:
let _row = Math.floor(index / columns); let row = parseInt(index / columns); 都可改成 let row = index / columns >> 0;
这个用位运算的效率会明显高于上面两个。
转成boolean值用!!
let mobile = !!ua.match(/iPhone|iPad|Android|iPod|Windows Phone/)
# 使用正则表达式做字符串处理
正则表达式可以很方便地处理字符串,通常只要一行代码就搞定了。
// 去掉全局的某一个字符,如去掉电话号码的-连接符
phoneNumer = phoneNumber.replace(/\-/g, "");
//或者反过来,把电话号码改成3-3-4的形式:
phoneNumber = phoneNumber.replace(/^(\d{3})(\d{3})(\d{4})$/, "$1-$2-$3");
# 函数注释
/**
* @desc 一个带参数的函数
* @param {string} a - 参数a
* @param {number} b=1 - 参数b默认值为1
* @param {string} c=1 - 参数c有两种支持的取值</br>1—表示x</br>2—表示xx
* @param {object} d - 参数d为一个对象
* @param {string} d.e - 参数d的e属性
* @param {string} d.f - 参数d的f属性
* @param {object[]} g - 参数g为一个对象数组
* @param {string} g.h - 参数g数组中一项的h属性
* @param {string} g.i - 参数g数组中一项的i属性
* @param {string} [j] - 参数j是一个可选参数
* @return {string} result
*/
function foo(a, b, c, d, g, j) {
...
return "";
}
以上内容参考:
掘金▪HTML/CSS/JS编码规范
腾讯IMWEB