一 业务开发和日常编写
此类规范从日常开发中总结,使用频率较高, 不断更新中
1、避免魔法变量和硬编码
// 魔法变量
//bad
if(a == 1) {
//do something
}
if(b == 2 && c == 3) {
//do something
}
//good => 提取公共变量到配置文件(也可以使用map),大写提取(这里省略)
const STATUS_CONFIG = {
IS_VIP: 1,
IS_LOGIN: 2,
IS_BIND: 3
}
if(STATUS_CONFIG.IS_VIP) {
//do something
}
if(STATUS_CONFIG.IS_LOGIN && STATUS_CONFIG.IS_BIND ) {
//do something
}
//硬编码
//bad 硬编码存在于两个方法域模块中
const funa = (reqs) => {
const token = reqs.hearders.get('auth')
if(token) {
localStorage.setItem('authToken',token)
}
}
const funb = () => {
const token = localStorage.getItem('authToken')
}
//good 提取到环境变量或者配置文件
const AUTO_TOKEN = 'AUTH_TOKEN'
const funa = (reqs) => {
const token = reqs.hearders.get('auth')
if(token) {
localStorage.setItem(AUTO_TOKEN,token)
}
}
const funb = () => {
const token = localStorage.getItem(AUTO_TOKEN)
}
2、避免多参数传递
//bad
const funb = (a, b, c, d, e) => {
//...
}
funb('name',100,20,'type',2)
//good 对象封装和解构
const funb = (obj) => {
const {a, b, c, ...others} = obj
//...
}
funb(obj)
3、避免多条件判断重复使用
//bad 魔法变量参考问题1
const fun = () => {
if(a == 1 && !b && d == 2 || c == 3) {
//...
}
}
if(a == 1 && !b && d == 2 || c == 3) {
//...
}
//good
const IS_BIND = () => {
return !!(a == 1 && !b && d == 2 || c == 3)
}
//or
// const IS_BIND = !!(a == 1 && !b && d == 2 || c == 3)
const fun = () => {
if(IS_BIND()) {
//...
}
}
if(IS_BIND()) {
//...
}
4、 避免多类似条件if/else
// if/else 未优化之前
/**
* 按钮点击事件
* @param { string } type
*/
const onPageClick = (type) => {
if (type === "1") {
showLog("a");
jumpTo("pageA");
} else if (type === "2") {
showLog("b");
jumpTo("pageB");
} else if (type === "3") {
showLog("c");
jumpTo("pageC");
} else if (type === "4") {
showLog("d");
jumpTo("pageD");
} else if (type === "5") {
showLog("e");
jumpTo("pageE");
} else {
showLog("f");
jumpTo("defaultF");
}
}
// key/value结构优化
// 除了使用object也可以使用 map 来进行优化(map的优势请自行查阅
const actions = {
1: ["a", "pageA"],
2: ["b", "pageB"],
3: ["c", "pageC"],
4: ["d", "pageD"],
5: ["e", "pageE"],
default: ["f", "defaultF"],
};
/**
* 按钮点击事件
* @param { string } type
*/
function onPageClick(type) {
let action = actions[type] || actions["default"];
// 打印日志
showLog(action[0]);
// 跳转页面
jumpTo(action[1]);
}
建议不要使用switch进行优化
代码更加臃肿不便于扩展和进一步优化
break使用不当造成判断步骤问题
5、避免嵌套地狱
//bad
funa().then(a => {
funb(a).then(b => {
func(b).then(c => {
doSomthing(c)
})
})
})
//recommend
funa().then(funb).then(func).then(c => doSomething).catch(err => console.err(err))
6、避免一条路走到黑
// -----------------------------------------------------------------优化前
需求:条件 1 已经绑定手机号 && 2 已经关注公众号 && 3 领取礼品
对应方法:绑定:isBind/funDoBind 关注 isLike/funDoLike 领取礼品 getGift
const checkActivity = () => {
if (isBind) {//如果已绑定
if (isLike) {//如果已关注
//则领取礼品
getGift();
} else {//如果未关注
//去关注
funDoLike(() => {
//关注成功的回调
getGift();
});
}
} else {//如果未绑定,去绑定
funDoBind(() => {
if (isLike) {//如果已关注
//则领取礼品
getGift();
} else {//如果未关注
//去关注
funDoLike(() => {
//关注成功的回调
getGift();
});
}
});
}
}
// --------------------------------------------------------优化后
以时间换空间:不满足直接返回再走一遍
const checkActivity = () => {
if(isBind && isLike) return getGift();
if(!isBind) {
funDoBind(() => {
return checkActivity()
})
}
if(!isLike) {
funDoLike(() => {
return checkActivity()
})
}
}
二、代码规范(js)
1、变量声明
所有声明必须严格执行const, let,不允许使用var(如果不是必要请使用const,因为在ts中字符串泛型let会出错
2、保留字
JavaScript
// bad
const a = {
default: {}, // default 是保留字
common: {}
}
// good
const a = {
defaults: {},
common: {}
}
3、引号问题
对字符串使用单引号,尽量不适用双引号
1一致性:可以在字符串内部使用另一种引号
2避免转义字符:双引号中包含双引号字符串
3与HTML结合使用:const htmlString = '<div class="container">This is an HTML element.</div>'
// bad
const a = "123"
// good
const a = '123'
4、链式复制
变量不要进行链式赋值,变量链式赋值会创建隐藏的全局变量(除非你懂得具体含义)
//----------------案例
// bad
let a = b = 2
// good
let a = 2
let b = 2
//--------------说明
1 变量覆盖:当你在链式赋值中使用相同的变量名时,后续的赋值会覆盖前面的赋值。这可能导致你意外地丢失数据。
let a = b = c = 10;
// 等同于 c = 10; b = 10; let a = b;
//如果忘记使用let和const会造成多个全局变量污染
2 对象引用:如果你在链式赋值中操作对象属性或数组元素,并且其中一个属性是一个对象引用,那么后续的赋值可能会影响前面的属性,因为它们都引用了同一个对象。
const obj = { prop: 1 };
const a = obj.b = obj.prop = 2;
//在这个例子中,a、obj.b 和 obj.prop 都将成为 2,因为它们引用了同一个对象。
5、避免多余变量的声明
6、创建对象
通常,字面量声明和构造函数声明都有各自的用途。推荐根据对象的复杂程度和功能需求来选择合适的声明方式
对于简单的、静态的数据对象,字面量声明更直观、简洁
const person = {
name: "Alice",
age: 30,
job: "Developer"
};
对于需要具有自定义方法和行为的对象,构造函数声明更适用
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
const person = new Person("Alice", 30, "Developer");
7、字符串拼接(尽量使用模板字符)
/ bad
const str = 'a' + 'b' + test
// good
const str = `ab${test}`
8、当你必须使用函数表达式(比如传递匿名函数)时,使用箭头函数标记
它将创建在 this 上下文中执行的函数版本,通常是您想要的,并且语法更简洁
// bad
[1, 2, 3].map(function(x) {
const y = x + 1
return x * y
})
// good
[1, 2, 3].map(x => {
const y = x + 1
return x * y
})
9、解构赋值
解构可以避免创建属性的临时引用
对象解构
// bad
function getFullName(user) {
const firstName = user.firstName
const lastName = user.lastName
return `${firstName} ${lastName}`
}
// good
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`
}
数组结构
const arr = [1, 2, 3, 4]
// bad
const first = arr[0]
const second = arr[1]
// good
const [first, second] = arr
函数回传参数解构
/**
函数需要回传多个值时,请使用对象的解构,而不是数组的解构。 ps: 这样可以非破坏性地随时增加或者改变属性顺序
*/
// bad
function doSomething() {
return [top, right, bottom, left]
}
// 如果是数组解构,那么在调用时就需要考虑数据的顺序
const [top, xx, xxx, left] = doSomething()
// good
function doSomething() {
return { top, right, bottom, left }
}
// 此时不需要考虑数据的顺序
const { top, left } = doSomething()
解构默认值
// bad
const { a, b } = { a: 3 }
// good
const { a = 10, b = 1 } = { a: 3 }
10、使用 === 和 !== 而非 == 和 !=
除非你懂得为何去使用
11、尽可能使用简介表达式
const name = ''
// bad
if (name === '') {
// ......
}
// good
if (!name) {
// ......
}
三目运算
const name = getName()??'-'
12、如果函数或全局中的 else 块后没有任何语句,可以删除 else
// bad
function getName() {
if (name) {
return name;
} else {
return 'unnamed';
}
}
// good
function getName() {
if (name) {
return name;
}
return 'unnamed';
}
13、尽量不要使用eval
eval会引起xss攻击;eval会干扰作用域链等等,不推荐在代码中使用eval
14、变量命名
1 常规小驼峰
let userInfo = {}
2 全局常量用大写字母,多个字母以下划线连接
const MATH_PI = 3.14
3 类名、组件名以大驼峰格式开头
4 枚举变量用大驼峰格式,枚举属性 使用全部字母大写,单词间下划线分隔
const Week = {
MONDAY: 0,
TUESDAY_TYPE: 1
}
15、boolean类型的变量建议使用 is或has开头
16、单行和多行注释(根据函数复杂度自行定义
17、永远不要直接使用 undefined 进行变量判断;使用 typeof 和字符串’undefined’对变量进行判断。
防止变量未声明的错误:如果你尝试访问一个未声明的变量,直接与 undefined 比较会导致引用错误(ReferenceError)。但是,使用 typeof 检查不会引发错误,它会返回字符串 "undefined",从而避免了异常。
//bad:如果person未定义 这会引发 ReferenceError
if (person === undefined) { ... }
//good
if (typeof person === 'undefined') { ... }
避免全局变量冲突:直接比较 undefined 可能会导致全局变量的冲突。如果某个变量名在当前作用域中没有被声明,JavaScript 将尝试在全局作用域中查找该变量。这可能导致意外的行为。
// 在全局作用域中有一个未声明的变量 person
if (person == undefined) {
// 这里的条件将通过,但可能不是你期望的结果
}
类型安全: 使用 typeof 进行比较可以确保变量的类型与预期的类型匹配。直接与 undefined 比较可能会出现类型转换问题,因为 JavaScript 中的类型转换规则可能会使得一些非预期的结果
// 变量 person 是字符串 "undefined"
var person = "undefined";
if (person == undefined) {
// 这里的条件通过,但可能不是你期望的结果
}
if (typeof person == "undefined") {
// 这里的条件不通过,因为变量 person 的类型不是 "undefined"
}
18、条件判断和循环最多三层
条件判断能使用三目运算的尽量使用三目运算;谨记不要写太长的三目运算
// not recommended
if(a) {
return 'conditionA'
} else {
return 'conditionB'
}
//recommended
return a?'conditionA':'conditionB'
如果超过3层请抽离成函数
// not recommended
return a?b?'conditionA':'conditionB':'conditionDefault'
//recommended
const checkConditionB = (a, b) => {
if(a) return b?'conditionA':'conditionB'
return 'conditionDefault'
}
三 代码规范(css)
1、尽量按照less和sass的格式进行书写
其中包括但不限于:变量提取、嵌套复用等等方式
2、简写
/* bad */
.geely {
padding-left: 15px;
padding-top: 20px;
padding-bottom: 20px;
padding-right: 15px;
}
/* good */
.geely {
padding: 20px 15px;
}
3、尽量不使用 !important 声明
4、嵌套层级(建议不超过3级)
5、可复用变量
/* bad */
.geely {
color: #fff;
border-color: #fff;
}
/* good */
$color: #fff;
.geely {
color: $color;
border-color: $color;
}
/*.less写法*/
/* bad */
.geely {
width: 100px;
}
.hwl {
width: 100px;
}
/* good */
@width: 10px;
.geely {
width: @width;
}
.hwl {
width: @width;
}
6、善用mixin
/* bad */
.geely-text {
display: inline-block;
white-space: nowrap;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
.geely-msg {
display: inline-block;
white-space: nowrap;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
/* good 抽离成mixin来调用*/
@mixin text-overflow() {
display: inline-block;
white-space: nowrap;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
.geely-text {
@include text-overflow();
}
.geely-msg {
@include text-overflow();
}
7、运算规范
/* bad */
.geely {
width: calc(100%-100px);
}
/* good */
.geely {
width: calc(100% - 100px);
}