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>

   var map = document.querySelector("#my-map");

   map.style.height ="600px";

</script>

有时候你需要在页面直接写一个script,要注意在一个script标签里面,代码的上下文都是全局作用域的,由于全局作用域比较复杂,查找比较慢。例如上面的map变量,第二行在使用的时候,需要在全局作用域查找一下这个变量,假设map是在一个循环里面使用,那可能就会有效率问题了。所以应该要把它搞成一个局部的作用域:


<script>

!function(){

   var map = document.querySelector("#my-map");

   map.style.height ="600px";

}()

</script>

上面用了一个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 =

   '<div>'+

   '    <span>1</span>'+

   '</div>';

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


var tpl =

`   <div>

       <span>1</span>

   </div>

`;

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


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++){

   tasks[j]();

}

但是上面代码的执行输出是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++){

   tasks[j]();

}

把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++){

   tasks[j]();

}

只改动了3个字符就达到了目的。因为for循环里面有个大括号,大括号就是一个独立的作用域,let定义的变量在独立的作用域里面它的值也是独立的。当然即使没写大括号for循环执行也是独立的。

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

如何让你的 JS 代码写得更漂亮相关推荐

  1. [html] 说说js代码写到html里还是单独写到js文件里哪个好?为什么?

    [html] 说说js代码写到html里还是单独写到js文件里哪个好?为什么? js和html还是分开比较好,一是各功能独立,界面比较干净,二是方便管理,关系清晰,三是方便引用,一些公共js独立导入可 ...

  2. js文件中可以写html吗,js代码写在HTML正常,分离成js文件再在HTML中引用不起作用...

    js代码写在HTML功能正常,分离成js文件再在HTML中引用却不起作用 js代码片段,功能是调用高德地图JS API,并做些布局调整 var map = new AMap.Map("con ...

  3. Smarty中直接加JS代码和将JS代码写在literal标签里

    采用Smarty模板的html怎么加入JS代码呢? 如果按一般平常添加方法,会出错 .因为 Smarty会将"{}"解析为自己的方法,和js中的"{}"会冲突. ...

  4. 如何让 JS 写得更漂亮

    网上有不少关于JS编写优化建议,这里我根据自己的经验提出一些比较有用的意见. 01按强类型风格写代码 JS是弱类型的,但是写代码的时候不能太随意,写得太随意也体现了编码风格不好.下面分点说明: (1) ...

  5. jS代码写在html什么位置,3种JavaScript代码书写位置和注意事项

    在网页中编写JavaScript代码时,有3种书写位置,分别是行内式.内嵌式(也称为嵌入式)和外部式(也称为外链式),下面分别进行讲解. 1. 行内式 行内式是指将单行或少量的JavaScript代码 ...

  6. 用canvas代码写或者three.js代码写一张截图,这张截图里面包含4张图片 ,其中3张图片有倾斜立体效果,剩下的一张是背景图...

    如果使用Canvas代码写,你可以使用Canvas 2D上下文的API来绘制倾斜的图像.你可以通过使用Canvas的transform()方法来旋转图像. 以下是一个使用Canvas绘制倾斜图像的示例 ...

  7. JS代码写简单购物车

    实现效果: CSS样式: <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compat ...

  8. 如何让你的 JS 写得更漂亮,看这篇就对了!

    网上有不少关于JS编写优化建议,这里我根据自己的经验提出一些比较有用的意见. 1. 按强类型风格写代码 JS是弱类型的,但是写代码的时候不能太随意,写得太随意也体现了编码风格不好.下面分点说明: (1 ...

  9. js 时间加减_【JS】550 简单几步让你的 JS 写得更漂亮

    作者:会编程的银猪 http://www.renfed.com/2017/04/29/effective-js-optimize/ 网上有不少关于 JS 编写优化建议,这里我根据自己的经验提出一些比较 ...

最新文章

  1. 创始人爆料!被谷歌收购前,DeepMind 已濒临破产
  2. suse mysql root密码忘记_SUSE11.4 找回 mysql root 密码?网上能找到的所有方法都试过了,不行......
  3. [转]HDR渲染器的实现(基于OpenGL)
  4. codeforces round 422 div2 补题 CF 822 A-F
  5. Redis 是怎么实现 “附近的人” 的?
  6. 【MM】需求类型清单
  7. with 关键字实现递归查询
  8. 了解ThreadLocal背后的概念
  9. OpenCV学习笔记(三):多通道图像分离、混合算子:split(),merge()
  10. 7-1 顶点的度 (15 分)
  11. android 灰色向白色渐变,iPhone-iOS的白色到透明渐变层为灰色
  12. 使用shell脚本将mysql数据导入HIve中
  13. ArcGIS API for Silverlight之配准JPG图片地图文字倾斜解决方案
  14. 数据库:delete语句
  15. 联想平板刷android,联想平板电脑刷机全教程【图文】
  16. java实现手机扫描二维码下载功能
  17. TensorFlow 从入门到精通(8)—— 泰坦尼克号旅客生存预测
  18. Android 7.1.1中SystemProperties详解
  19. 【光电智造】机器人视觉伺服技术
  20. 単語境界/非単語境界(¥b, ¥B)

热门文章

  1. python极客学院爬虫_学习极客学院多线程爬虫课程的收获
  2. https://www.cnblogs.com/xinxin1994/p/5257472.html oracle 创建用户
  3. 如何改typecho主题头像_微信头像分析:一次主观的解读
  4. 解除.netMVC4上传文件不能超过30M的限制
  5. 在Ubuntu Server 22.04 LTS 上部署BT面板和Seatable
  6. Linux系统调用之fork,getpid,getppid函数(进程相关函数)
  7. java电商项目搭建-------商品详情页模块
  8. POJ1080 Human Gene Functions(LCS)
  9. 微信扫码支付(模式二)
  10. 一阶动量与二阶动量的角度理解优化