1、按强类型风格写代码
js是弱类型的,但是写代码的时候不能太随意,写得太随意也体现了编码风格不好。下面分点说明:

(1)定义变量的时候要指明类型,告诉JS解释器这个变量是什么数据类型的,而不要让解释器去猜,例如不好的写法:

var num,
str,
obj;
声明了三个变量,但其实没什么用,因为解释器不知道它们是什么类型的,好的写法应该是这样的:

var num =0,
str =’’,
obj =null;
定义变量的时候就给他一个默认值,这样不仅方便了解释器,也方便了阅读代码的人,他会在心里有数——知道这些变量可能会当作什么用。

(2)不要随意地改变变量的类型,例如下面代码:

var num =5;
num ="-"+ num;
第1行它是一个整型,第2行它变成了一个字符串。因为JS最终都会被解释成汇编的语言,汇编语言变量的类型肯定是要确定的,你把一个整型的改成了字符串,那解释器就得做一些额外的处理。

并且这种编码风格是不提倡的,有一个变量第1行是一个整型,第10行变成了一个字符串,第20行又变成了一个object,这样就让阅读代码的人比较困惑,上面明明是一个整数,怎么突然又变成一个字符串了。好的写法应该是再定义一个字符串的变量:

var num =5;
var sign ="-"+ num;
(3)函数的返回类型应该是要确定的,例如下面不确定的写法:

function getPrice(count){
if(count <0)return"";
elsereturn count *100;
}
getPrice这个函数有可能返回一个整数,也有可能返回一个空的字符串。这样写也不太好,虽然它是符合JS语法的,但这种编码风格是不好的。

使用你这个函数的人会有点无所适从,不敢直接进行加减乘除,因为如果返回字符串进行运算的话值就是NaN了。函数的返回类型应该是要确定的,如下面是返回整型:

function getPrice(count){
if(count <0)return-1;
elsereturn count *100;
}
然后告诉使用者,如果返回-1就表示不合法。如果类型确定,解释器也不用去做一些额外的工作,可以加快运行速度。

2、减少作用域查找
(1)不要让代码暴露在全局作用域下

例如以下运行在全局作用域的代码:

有时候你需要在页面直接写一个script,要注意在一个script标签里面,代码的上下文都是全局作用域的,由于全局作用域比较复杂,查找比较慢。

例如上面的map变量,第二行在使用的时候,需要在全局作用域查找一下这个变量,假设map是在一个循环里面使用,那可能就会有效率问题了。

所以应该要把它搞成一个局部的作用域:

上面用了一个function制造一个局部作用域,也可以用ES6的块级作用域。

由于map这个变量直接在当前的局部作用域命中了,所以就不用再往上一级的作用域(这里是全局作用域)查找了,而局部作用域的查找是很快的。同时直接在全局作用域定义变量,会污染window对象。

(2)不要滥用闭包

闭包的作用在于可以让子级作用域使用它父级作用域的变量,同时这些变量在不同的闭包是不可见的。

这样就导致了在查找某个变量的时候,如果当前作用域找不到,就得往它的父级作用域查找,一级一级地往上直到找到了,或者到了全局作用域还没找到。

因此如果闭包嵌套得越深,那么变量查找的时间就越长。如下:

function getResult(count){
count++;
function process(){
var factor =2;
return count * factor -5;
}
return process();
}
上面的代码定义了一个process函数,在这个函数里面count变量的查找时间要高于局部的factor变量。其实这里不太适合用闭包,可以直接把count传给process:

function getResult(count){
count++;
function process(count){
var factor =2;
return count * factor -5;
}
return process(count);
}
这样count的查找时间就和factor一样,都是在当前作用域直接命中。

这个就启示我们如果某个全局变量需要频繁地被使用的时候,可以用一个局部变量缓存一下,如下:

var url ="";
if(window.location.protocal ===“https:”){
url =“wss://xxx.com”+ window.location.pathname + window.location.search;
}
频繁地使用了window.location对象,所以可以先把它缓存一下:

var url ="";
var location = window.location;
if(location.protocal ===“https:”){
url =“wss://xxx.com”+ location.pathname + location.search;
}
搞成了一个局变变量,这样查找就会明显快于全局的查找,代码也可以写少一点。

3、避免==的使用
这里你可能会有疑问了,有些人喜欢用==,有些人喜欢用===,大家的风格不一样,你为什么要强制别人用=呢?习惯用的人,不能仅仅是因为比=少敲了一次键盘。为什么不提倡用==呢?

(1)如果你确定了变量的类型,那么就没必要使用==了,如下:

if(typeof num !=“undefined”){

}
var num = parseInt(value);
if(num ==10){

}
上面的两个例子都是确定类型的,一个是字符串,一个是整数。就没必要使用了,直接用=就可以了。

(2)如果类型不确定,那么应该手动做一下类型转换,而不是让别人或者以后的你去猜这里面有类型转换,如下:

var totalPage =“5”;
if(parseInt(totalPage)===1){

}
(3)使用==在JSLint检查的时候是不通过的:

if(a == b){

}
如下JSLint的输出:

Expected ‘=’ and instead saw ‘’.
(4)并且使用==可能会出现一些奇怪的现象,这些奇怪的现象可能会给代码埋入隐患:

null==undefined //true

‘’ == ‘0’ //false

0 == ‘’ //true

0 == ‘0’ //true


’ == 0 //true

new String(“abc”) == “abc” //true

new Boolean(true) == true //true

true == 1 //true
上面的比较在用===的时候都是false,这样才是比较合理的。例如第一点null居然会等于undefined,就特别地奇怪,因为null和undefined是两个毫无关系的值,null应该是作为初始化空值使用,而undefined是用于检验某个变量是否未定义。

这和第1点介绍强类型的思想是相通的。

4、 合并表达式
如果用1句代码就可以实现5句代码的功能,那往往1句代码的执行效率会比较高,并且可读性可能会更好

(1)用三目运算符取代简单的if-else

如上面的getPrice函数:

function getPrice(count){
if(count <0)return-1;
elsereturn count *100;
}
可以改成:

function getPrice(count){
return count <0?return-1: count *100;
}
这个比写一个if-else看起来清爽多了。当然,如果你写了if-else,压缩工具也会帮你把它改三目运算符的形式:

function getPrice(e){return0>e?-1:100*e}
(2)连等

连等是利用赋值运算表达式会返回所赋的值,并且执行顺序是从右到左的,如下:

overtime = favhouse = listingDetail ={…}
有时候你会看到有人这样写:

var age =0;
if((age =+form.age.value)>=18){
console.log(“你是成年人”);
}else{
consoe.log(“小朋友,你还有”+(18- age)+“就成年了”);
}
也是利用了赋值表达式会返回一个值,在if里面赋值的同时用它的返回值做判断,然后else里面就已经有值了。上面的+号把字符串转成了整数。

(3)自增

利用自增也可以简化代码。如下,每发出一条消息,localMsgId就自增1:

chatService.sendMessage(localMsgId++, msgContent);
5、减少魔数

例如,在某个文件的第800行,冒出来了一句:

dialogHandler.showQuestionNaire(“seller”,“sell”,5,true);
就会让人很困惑了,上面的四个常量分别代表什么呢,如果我不去查一个那个函数的变量说明就不能够很快地意会到这些常量分别有什么用。这些意义不明的常量就叫“魔数”。

所以最好还是给这些常量取一个名字,特别是在一些比较关键的地方。例如上面的代码可改成:

var naireType =“seller”,
dialogType =“sell”,
questionsCount =5,
reloadWindow =true;
naireHandler.showNaire(naireType, dialogType, questionsCount, reloadWindow);

这样意义就很明显了。

6、使用ES6简化代码
ES6已经发展很多年了,兼容性也已经很好了。恰当地使用,可以让代码更加地简洁优雅。

(1)使用箭头函数取代小函数

有很多使用小函数的场景,如果写个function,代码起码得写3行,但是用箭头函数一行就搞定了,例如实现数组从大到小排序:

var nums =[4,8,1,9,0];
nums.sort(function(a, b){
return b - a;
});
//输出[9, 8, 4, 1, 0]
如果用箭头函数,排序只要一行就搞定了:

var nums =[4,8,1,9,0];
nums.sort(a, b => b - a);
代码看起来简洁多了,还有setTimeout里面经常会遇到只要执行一行代码就好了,写个function总感觉有点麻烦,用字符串的方式又不太好,所以这种情况用箭头函数也很方便:

setTimeout(()=> console.log(“hi”),3000)
箭头函数在C++/Java等其它语言里面叫做Lambda表达式,Ruby比较早就有这种语法形式了,后来C++/Java也实现了这种语法。

当然箭头函数或者Lambda表达式不仅适用于这种一行的,多行代码也可以,不过在一行的时候它的优点才比较明显。

(2)使用ES6的class

虽然ES6的class和使用function的prototype本质上是一样的,都是用的原型。但是用class可以减少代码量,同时让代码看起来更加地高大上,使用function要写这么多:

functionPerson(name, age){
this.name = name;
this.age = age;
}

Person.prototype.addAge =function(){
this.age++;
};

Person.prototype.setName =function(name){
this.name = name;
};
使用class代码看加地简洁易懂:

classPerson{
constructor(name, age){
this.name = name;
this.age = age;
}
addAge(){
this.age++;
}
setName(name){
this.name = name;
}
}
并且class还可以很方便地实现继承、静态的成员函数,就不需要自己再去通过一些技巧去实现了。

(3)字符串拼接

以前要用+号拼接:

var tpl =

’+
’ 1’+

’;
现在只要用两个反引号“`”就可以了:

var tpl =
`


1

`; 另外反引号还支持占位替换,原本你需要:

var page =5,
type = encodeURIComponet("#js");
var url ="/list?page="+ page +"&type="+ type;
现在只需要:

var url =/list?page=${page}&type=${type};
就不用使用+号把字符串拆散了。

(4)块级作用域变量

块级作用域变量也是ES6的一个特色,下面的代码是一个任务队列的模型抽象:

var tasks =[];
for(var i =0; i <4; i++){
tasks.push(function(){
console.log("i is "+ i);
});
}
for(var j =0; j < tasks.length; j++){
tasksj;
}
但是上面代码的执行输出是4,4,4,4,并且不是想要输出:0,1,2,3,所以每个task就不能取到它的index了,这是因为闭包都是用的同一个i变量,i已经变成4了,所以执行闭包的时候就都是4了。

那怎么办呢?可以这样解决:

var tasks =[];
for(var i =0; i <4; i++){
!function(k){
tasks.push(function(){
console.log("i is "+ k);
});
}(i);
}
for(var j =0; j < tasks.length; j++){
tasksj;
}
把i赋值给了k,由于k它是一个function的一个参数,每次执行函数的时候,肯定会实例化新的k,所以每次的k都是不同的变量,这样就输出就正常了。

但是代码看起来有点别扭,如果用ES6,只要把var改成let就可以了:

var tasks =[];
for(let i =0; i <=4; i++){
tasks.push(function(){
console.log("i is "+ i);
});
}
for(var j =0; j < tasks.length; j++){
tasksj;
}
只改动了3个字符就达到了目的。因为for循环里面有个大括号,大括号就是一个独立的作用域,let定义的变量在独立的作用域里面它的值也是独立的。

当然即使没写大括号for循环执行也是独立的。

除了以上几点,ES6还有其它一些比较好用的功能,如Object的assign,Promise等,也是可以帮助写出简洁高效的代码。

总结
以上列了我自己在实际写代码过程中遇到的一些问题和一些个人认为比较重要的方面,其它的还有变量命名、缩进、注释等,这里就不提及了。

写代码的风格也体现了编程的素养,有些人的代码看起来非常地干净利落,而有些人的代码看起来让人比较痛苦。

这种编程素质的提升需要有意识地去做一些改进,有些人虽然代码写得很烂,但是他自己并不觉得有什么问题。

这就需要多去学下别人的代码,甚至学一下其它语言的书写,两者一比较就能发现差异,或者看下这方面的书,像什么代码大全之类的。

如何学好前端开发是关键:

前端技术每年都会不断更新,自学前端容易学不到最前沿的课程,学习前端开发建议大家还是要选择培训为好,推荐爱创课堂,是一家专门做前端教育的学校,爱创课堂是一家以就业为导向的前端培训学校,所学习的就是企业所需要的,培养企业最需要的前端工程师为企业理念,授课以实战课程为主,更多的学习大项目对以后工作有帮助,毕业后轻松就业!

web前端 - 写出漂亮JavaScript代码的实用技巧相关推荐

  1. 6个帮助你写出漂亮JavaScript代码的实用技巧

    来源 | www.fly63.com 我觉得写好代码和作文章差不多,无外乎:工整.优雅.拒绝重复.惜字如金.对代码有感情,每一行都应该尽心尽力,并且还要有把所有代码扔垃圾篓之后再重写两遍的冲动,一旦有 ...

  2. 如何写出漂亮的代码:七个法则

    如何写出漂亮的代码:七个法则. 首先我想说明我本文阐述的是纯粹从美学的角度来写出代码,而非技术.逻辑等.以下为写出漂亮代码的七种方法: 1, 尽快结束 if语句 例如下面这个JavaScript语句, ...

  3. 只用这 6 个字符,就可以写出任意 JavaScript 代码!

    作者简介: 李中凯老师,8年前端开发,前端负责人,擅长JavaScript/Vue. 公众号:1024译站 掘金文章专栏:https://juejin.im/user/57c7cb8a0a2b5800 ...

  4. 写出漂亮 Python 代码的 20条准则

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 来自 | 架构头条 按照<代码整洁之道>的说法,"花在阅读和编码 ...

  5. 如何写出漂亮的代码——臃肿的service

    在我们的项目架构中,数据库访问通常是用entity framework(EF),另外有一个很重要的service层,主要用于跟EF交互,也会在这一层封装大部分的业务逻辑.通常情况下,我们会用一个接口将 ...

  6. 前端写出优雅的代码,融会贯通es6

    提交自身能力必备 async handFn () {const getLogin = () => {}// 1if (this.Val) return console.log('a是大于0的') ...

  7. JavaScript实现:如何写出漂亮的条件表达式

    摘要:就让我们看看以下几种常见的条件表达场景,如何写的漂亮! 本文分享自华为云社区<如何写出漂亮的条件表达式 - JavaScript 实现篇>,原文作者:查尔斯. 条件表达式,是我们在c ...

  8. 写出漂亮代码的七种方法

    首先我想说明我本文阐述的是纯粹从美学的角度来写出代码,而非技术.逻辑等.以下为写出漂亮代码的七种方法: 1.尽快结束 if 语句 例如下面这个JavaScript语句,看起来就很恐怖:  functi ...

  9. 写出漂亮代码的45个小技巧

    不知道大家有没有经历过维护一个已经离职的人的代码的痛苦,一个方法写老长,还有很多的if else ,根本无法阅读,更不知道代码背后的含义,最重要的是没有人可以问,此时只能心里默默地问候这个留坑的兄弟. ...

最新文章

  1. YOLOv2和YOLOv3效果对比
  2. java代码运行linux shell操作
  3. php 把一个数组分成有n个元素的二维数组的算法
  4. java mariadb 使用,java连接mariaDB的设置,java连接mariadb
  5. 爬虫requests高阶篇详细教程
  6. python-函数的局部变量
  7. 无人驾驶(pid算法)
  8. python学习精华——成长篇
  9. openresty 搭建
  10. 【CCCC】L3-010 是否完全二叉搜索树 (30分),完全二叉树判断+层次遍历(奇怪的方法)
  11. ASP.NET AJAX中防止用户多次提交页面
  12. 反击ARP欺骗 我和网络执法官的战斗
  13. jdbc:mysql:replication_使用Mysql的Replication功能实现数据库同步
  14. Linux下安装常用软件
  15. 2022年认证杯SPSSPRO杯数学建模D题(第一阶段)食品风味与风味物质求解全过程文档及程序
  16. 2021年材料员-岗位技能(材料员)新版试题及材料员-岗位技能(材料员)考试试卷
  17. 【永恒之蓝】最新勒索软件WannaCrypt病毒感染前后应对措施
  18. 智能电动自行车充电桩系统解决方案
  19. SpringBoot2.0 - 集成JWT实现token验证
  20. 看完《第一行代码-第三版》- 郭霖 这本书后的总结

热门文章

  1. Python 介绍及相关资料
  2. 图解 | 5G基站是怎样安装的?
  3. C/C++ linux 时间戳
  4. 三星手机出货量取得增长,超越华为手机重夺全球第一
  5. 零点工作室暑假集训(AtCoder--ABC266)
  6. re.match()正则表达式
  7. linux文件的三种时间,修改时间、状态时间和读取时间
  8. 服务器静态页面分享微信,JS中静态页面如何实现微信分享功能
  9. 在线教育平台的盈利模式有哪些?
  10. 多线程的几种实现方法详解