当前位置: 首页 > news >正文

你一定要知道的代码规范(进阶)

一、javascript编码规范

  • 实际上,编码标准是有争议的,每个人可能都有自己的标准,但对标准应该是什么样的,则似乎很少能达成共识。
  • 但编码标准意味着,通过共同语言和一致的结构,把开发人员从无意义的工作中解放出来。把重心放在功能逻辑上去。
  • 一个好的标准能提供清晰明了的意图,是有效工作所必需的。

比较好的Javascript编码应该符合以下标准:

  • 编码错误的可能性降至最低(做好容错处理)* 代码适合大规模的项目和团队(一致的、可读的、可扩展的、可维护的)* 鼓励编码的效率、效果和复用(低耦合,高复用)* 鼓励使用JavaScript的优点,避免使用它的缺点(缺点还是不少的,扬长避短)* 开发团队通用,无排他性### 二、 使用一致的缩进和行长

  • 代码被阅读的次数比编写它的次数要多得多* 所以维护性、可读性是第一的(如果你不想被后面接手的人骂娘的话,就要做好这点)* 不知道大家有没有发现,报纸上的文本列都在50~80个字符的长度之间。* 对人类的眼睛来说,超过80个字符的某一行,看起来会逐渐变得吃力(有相关科学研究表明)所以我们得出来的结论是:

  • 每级代码缩进两个空格* 每行限制为78个字符* 这也是大厂通用写法,最为标准, 代码示例:```
    class Index extends Component {state = {navList: [{ name: ‘开始’, index: 0, key: ‘all’ },{ name: ‘结束’, index: 1, key: ‘sell’ },{ name: ‘进行中’, index: 2, key: ‘out’ },],pageTop: 0,navActive: 0,currentKey: ‘all’,page: 1,goodsData: {},hasMore: true,listLoading: false}
    }


### 三、 按段落组织代码

在编排代码的时候,要以清晰明白为目标,而不是减少代码的字节数该有的**空格**、**空白**都不能少

* 按逻辑段落组织代码,段落之间要**空行*** 每一行最多只包含一条语句或赋值语句,但是允许**每行**同时声明多个变量* 运**算符**和**变量**之间要有**空格**,更容易地识别变量* 每个**逗号**之后要有**空格*** 在段落内,相似的**运算符**要**对齐*** 缩进注释,缩进量和所解释的代码**相同**```
// 把一个或多个声明放在一行上,但每行只有一条赋值语句
let 
	z, x, c, v, d,
	a = l,
	b = 2,
	arr = [1, 2, 3],
	obj = {aa: 1, bb: "张三"},
	name = "法外狂徒张三";

// 在下一行段落的前面添加空行
// 函数将文本写入消息容器
print_msg = function ( msg_text ){// 缩进注释,和它所描述的段落层级一致// .text() 防止xss注入$('#sl').text( msg_text );
};

// 函数返回随机数
get_rangdom = function ( num_arg ){return Math.random() * numn_arg;
};

// 初始化值
x = get_random(10 );
y = get_random(20 );
r = get_random( 360 );

// 添加空白,对齐相似的元素,相似的语句更容易阅读
x += 10 + num;
y -= 20 - num; 

三、 换行要一致

  • 在运算符的前面换行,开发者检查更加方便
  • 把后续的语句缩进一个层次,比如使用两个空格
  • 逗号分隔符的后面换行
  • 方括号或者括号单独占一行。清楚地表明这是语句的结尾,不会迫使读者横向扫寻分号、
// 将运算符放在左边,排成一列
let str = '我知道你也在向我靠近,'
		+ '星河万顷都是你的见面礼。'
		+ '所以我也走向了你,'
		+ '暮色千里皆是我的回礼。'
		+ '今夜星光月夜皆归你,我也归你~'

// 方括号单独占一行,下一条语句就容易识别了
// 使用尾部逗号,更容易维护
let addressArr = ['湖南省','湖北省','广西省','江西省','江苏省','内蒙古自治区','台湾省','澳门
]; 

四、 命名规范

  • 变量名使用a - z、A - Z、0 - 9、下划线和$符号* 变量名不要以数字开头* 语义化(看其名,知其意)* 当变量作用域是整个模块时使用驼峰式(模块名字空间的所有地方都可以访问该变量)* 当变量作用域不是整个模块时使用下划线 (模块名字空间内的某个函数的局部变量)* 确保所有模块作用域内的变量至少有两个音节,这样作用域就会很清晰(例如下:)用户中心 ⇒ userCenter 商品列表 ⇒ goodsList 消息通知 ⇒ messageInfo

再来一组例子:

变量初始名局部作用域模块作用域
strdirection_strdirectionStr
idgoods_idgoodsId
msguser_msguserMsg
  • 全局变量用 const 定义,常量性质,字母全部大写(尽量少定义)

五、 命名空间

  • 早期的JavaScript代码比较简单,单独在一张页面上使用,所以大部分时间不需要考虑命名空间的问题,使用全局变量,而不会有什么影响。* 但是随着JavaScript应用的蓬勃发展和第三方类库的普遍使用,全局变量的数据可能会急剧上升* 地域之门从此便开启了。(比如,当两个代码库声明了相同的全局变量时)* 使用单一的全局函数,把其他所有变量的作用域限制在该函数里面,就可以极大地减少这种问题```
    // 模拟一个第三方库 =>
    jQuery (function(window){
    // 此变量只会在此区域生效,使用完之后垃圾回收机制自动回收
    // 不会污染全局变量
    let jquery = {}; })(window)

* 命名空间的细粒度划分

// 在 jquery.js 中
let jquery = (function () {// some code here
}());

// 在 jquery.dom.js 中
let jquery.dom= (function () {// some code here
}());

// 在 jquery.css.js 中
let jquery.css = (function () {// some code here
}());


### 六、 松耦合,高复用

* 当修改一个组件而不需要更改其他组件时,就做到了松耦合* 耦合度视情况而定,复用性组件必须低耦合如何松耦合?

* 将JS从CSS中抽离:不要使用CSS表达式

//不好的做法
.box{width: expression(document.body.offsetWidth + ’px’)}


* 将CSS从JS中抽离:通过JS修改CSS样式时,使用className或classList,不要逐条修改style样式

//不好的做法一
ele.style.color = ‘red’;
ele.style.left= ‘10px’;
//不好的做法二
ele.style.cssText =‘color:red;left:10px;’;

.reveal{color:red;left:10px;}
//好的做法一
ele.className += ‘reveal’;
//好的做法二
ele.classList.add(‘reveal’);


* 将JS从HTML中抽离:从JS文件放入外置文件中* 将HTML从JS中抽离:不要在innerHTML中拼接DOM结构,而是使用字符串模板,如handlerbars### 七、 函数优化

* 在javascript开发中,大部分时间都在与函数打交道,所以希望这些函数有着良好的命名,函数体内包含的逻辑清晰明了。* 如果一个函数过长,不得不加上若干注释才能让这个函数显得易读一些,那这些函数就很有必要进行重构* 如果在函数中有一段代码可以被独立出来,那最好把这些代码放进另外一个独立的函数中,这是一种很常见的优化工作。* 项目越大,必须拆分得越细,好维护(函数也是如此)**这样做的好处主要有以下几点:**

* 避免出现超大函数* 独立出来的函数有助于代码复用* 独立出来的函数更容易被覆写* 独立出来的函数如果拥有一个良好的命名,它本身就起到了注释的作用**比如在一个负责取得用户信息的函数里面,还需要打印跟用户信息有关的信息,那么打印的语句就可以被封装在一个独立的函数里:**

let getUserInfo = function(){ajax( ‘http:// xxx.com/userInfo’, function( data ){console.log( 'userId: ’ + data.userId );console.log( 'userName: ’ + data.userName );console.log( 'nickName: ’ + data.nickName );});
};
//改成:
let getUserInfo = function(){ajax( ‘http:// xxx.com/userInfo’, function( data ){printDetails( data );});
};
let printDetails = function( data ){console.log( 'userId: ’ + data.userId );console.log( 'userName: ’ + data.userName );console.log( 'nickName: ’ + data.nickName );
};


* 调用一个函数时需要传入多个参数,那这个函数是让人望而生畏的* 必须搞清楚这些参数代表的含义,必须小心翼翼地把它们按照顺序传入该函数。* 在实际开发中,向函数传递参数不可避免,但应该尽量减少函数接收的参数数量```
function cssTransform(ele, attr, val){// ele 要操作的元素// attr 运动属性 缩放,旋转// val 具体值if(!ele.transform){ele.transform = {};}if(typeof val === "undefined"){// 取值阶段// 取不到 设置默认值if(typeof ele.transform[attr] === "undefined"){switch(attr){case "scale":case "scaleX":case "scaleY":case "scaleZ":// attr是scale 默认值是1 其它都是0ele.transform[attr] = 1;break; default:ele.transform[attr] = 0; }}// 取值完毕 返回该值return ele.transform[attr];}else{// 赋值阶段ele.transform[attr] = val;// 设置属性 方便取值let transformVal = "";for(var s in ele.transform){switch(s){case "scale":case "scaleX":case "scaleY":case "scaleZ":transformVal += " " + s + "("+(ele.transform[s])+")";break;case "rotate":case "rotateX":case "rotateY": case "rotateZ": case "skewX":case "skewY":transformVal += " " + s + "("+(ele.transform[s])+"deg)";break;default:transformVal +=" " + s + "("+(ele.transform[s])+"px)";}ele.style.WebkitTransform = ele.style.transform = transformVal;}}
} 
  • 我们需要传入三个参数,这就导致了传参的复杂性* 可以将它绑定到HTML元素上,减少传参```
    HTMLElement.prototype.cssTransform = function (prop, value){var transform,transformValue = “”;if(this.transform === undefined) {this.transform = transform = Object.create(null);}if(value !== undefined){// 赋值阶段this.transform[prop] = value;transform = this.transform;for(var name in transform){switch(name){case “scale”:case “scaleX”:case “scaleY”:case “scaleZ”:transformValue += " " + name + “(”+ transform[name]+“)”;break;case “rotate”:case “rotateX”:case “rotateY”: case “rotateZ”: case “skewX”:case “skewY”:transformValue += " " + name + “(”+ transform[name] + “deg)”;break;default:transformValue +=" " + name + “(”+ transform[name] + “px)”;}this.style.WebkitTransform = this.style.transform = transformValue;}}else{// 取值return this.transform[prop];}
    }

### 八、 条件优化

* 如果一个函数体内有一些条件分支语句,而这些条件分支语句内部散布了一些重复的代码,那么就有必要进行合并去重工作* 假如有一个分页函数paging(),该函数接收一个参数currPage,currPage表示即将跳转的页码* 在跳转之前,为防止currPage传入过小或者过大的数字,要手动对它的值进行修正,详见如下代码```
let paging = function( currPage ){if ( currPage == 0 ){currPage = 0;jump( currPage ); // 跳转}else if ( currPage == totalPage ){currPage = totalPage;jump( currPage ); // 跳转}else{jump( currPage ); // 跳转}
}; 
  • 可以看到,负责跳转的代码jump(currPage)在每个条件分支内都出现了,所以完全可以把这句代码独立出来
let paging = function( currPage ){if ( currPage == 0 ){currPage = 0;}else if ( currPage == totalPage ){currPage = totalPage;}jump( currPage ); // 把jump 函数独立出来
}; 
  • 在程序设计中,复杂的条件分支语句是导致程序难以阅读和理解的重要原因,而且容易导致一个庞大的函数* 假设现在有一个需求是编写一个计算商品价格的 getPrice(),商品的计算只有一个规则:如果当前正处于夏季,那么所有冬装将以5折出售```
    let getPrice = function( price ){let date = new Date();if ( date.getMonth() > 6 &&date.getMonth() < 10 ){ // 冬天return price * 0.5;}return price;
    };

* 判断是否处于夏季

if ( date.getMonth() > 6 &&date.getMonth() < 10 )


* 这句代码要表达的意思很简单,就是判断当前是否正处于夏天(7 - 9月)。* 尽管这句代码很短小,但代码表达的意图和代码自身还存在一些距离,阅读代码的人必须要多花一些精力才能明白它传达的意图。* 其实可以把这句代码提炼成一个单独的函数,既能更准确地表达代码的意思,**函数名本身又能起到注释的作用**```
let isSummer = function(){let date = new Date();return date.getMonth() > 6 && date.getMonth() < 10;
};

let getPrice = function( price ){if ( isSummer() ){ // 夏天return price * 0.5;}return price;
}; 

九、循环优化

  • 在函数体内,如果有些代码实际上负责的是一些重复性的工作* 合理利用循环不仅可以完成同样的功能,还可以使代码量更少* 以for循环为例,最常规写法
for (let i = 0; i < arr.length; i++) { // do something... } 
  • 大多数人都是这种写法,这种写法的缺点在于,每次循环都要去读取一次数组的长度,性能上并不友好

变量情况的优化写法

for (let i = 0, j = arr.length; i < j; i++) {// do something...
} 
  • 将长度进行存储,之后循环无需再去读取长度* 这只是上面写法的一种变体,另一种写法而已,谈不上优化。因为无块级作用域,所以和上面的效果是一样的优化版
for (let i = arr.length - 1; i >= 0; i--) {// do something...
} 
  • 推荐的写法,它在第上面的基础上节约了一个变量

十、 提升js性能

  • 性能是创建网页或应用程序时最重要的一个方面,特别是加载性能,如果让用户等久了,别人干脆不等了,会造成用户流失* 用户对于应用的体验普遍要求提高了(现在来说,2s 内打不开网页的都是不合格的网站)* 应用的性能瓶颈,依然是在js上* 未使用的功能性代码以及与之相关的代码(它一样的会编译,运行)* 多余的依赖(不需要的及时删除)* 数组与对象避免使用构造函数构造函数是啥? new Array(), new Object()等
demoObj = () => {let obj = new Object()obj.name = '朱小明'obj.age = 10obj.sex = '男'return obj
} 
  • 推荐写法
demoObj = () => {let obj = {name: '朱小明',age: 10,sex: '男'}return obj
} 
  • 避免全局变量* js 的垃圾回收机制是不会销毁全局变量的* 所以它会常驻内存* 合理使用闭包* 闭包可以提供面向对象编程的便利,有私有属性和方法* 由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存* 过度使用闭包可能会导致内存占用过多的问题。* 所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露* 减少循环中的活动* 循环本来就耗性能(特别是数据量大的)* 方法尽量不要放在循环中执行(执行多次,特别是逻辑复杂的方法,后果可想而知)

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

相关文章:

  • 普陀区网站建设/站长工具ip地址查询
  • 雄县没有做网站的公司/最新国际新闻头条新闻
  • 网站制作应该注意到的问题/百度关键词排名联系方式
  • 如何申请网站备案号/百度一下搜索
  • 常州seo关键词排名/全面落实疫情防控优化措施
  • 涂料厂做网站有用吗/如何做品牌推广方案
  • [Vue]插件
  • 大话西游服务端开服架设服务器搭建教程
  • 第三章Linux环境基础开发工具使用(yum+rzsz+vim+g++和gcc+gdb+make和Makefile+进度条+git)
  • C++(类与对象)是纸老虎吗?
  • 这些Java基础知识,诸佬们都还记得嘛(学习,复习,面试都可)
  • 00后表示真干不过,部门新来的00后测试员已把我卷崩溃,想离职了...
  • 每日一练<2>
  • Vue——组件间常用通信方式详解
  • 【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
  • 【开发心得】electron iohook集成使用方案
  • Hive高手之路:二、hive数据分析实验
  • 猿创征文|破世界纪录的国产数据库 - OceanBase