网上有很多优化JS写法的建议。在此我根据自己的经验提出一些有益的建议。1、用强类型风格写代码JS是弱类型的,但是写代码的时候不能太随意。写得太随意也反映了一种糟糕的编码风格。解释如下几点:(1)定义变量时,指定类型,告诉JS解释器该变量是什么数据类型,不要让解释器去猜,比如写的不好:varnum,str,obj;declared三个变量,但是没用,因为解释器不知道它们是什么类型,好的写法应该是这样:varnum=0,str='',obj=null;在定义一个变量的时候,给他一个默认值,这样既方便了解释器,也方便了阅读代码的人。他会知道这些变量可能有什么用。(2)不要随意改变变量的类型,比如下面的代码:varnum=5;num="-"+num;它在第一行是一个整数,在第二行变成一个字符串。因为JS最终会被解释成汇编语言,所以必须确定汇编语言变量的类型。如果你把一个整数变成一个字符串,解释器将不得不做一些额外的处理。并且不提倡这种编码风格。有一个变量,第一行是一个整数,第10行变成了一个字符串,第20行变成了一个对象,看代码的人很迷惑,上面明明是整数,怎么突然又变成字符串了。一个好的写法应该是再定义一个字符串变量:varnum=5;varsign="-"+num;(3)函数的返回类型要确定,比如下面不确定的写法:functiongetPrice(count){if(count<0)return"";elsereturncount*100;}getPrice这个函数可能返回一个整数或空字符串。这样写不太好,虽然符合JS语法,但是这种编码风格不好。用你这个函数的人会有点不知所措,不敢直接加减乘除,因为如果用返回的字符串来计算,这个值就是NaN。函数的返回类型要确定,比如返回整数类型:functiongetPrice(count){if(count<0)return-1;elsereturncount*100;}然后告诉用户,如果返回-1,它意味着非法。如果确定了类型,解释器就不需要做一些额外的工作,可以加快运行速度。2.减少范围搜索(1)不要将代码暴露在全局范围内。比如下面在全局范围内运行的代码:有时候需要写一个脚本直接在页面上。请注意,在脚本标记中,代码的上下文处于全局范围内。因为全局范围比较复杂,所以搜索比较慢。比如上面的map变量,当使用到第二行的时候,需要在全局范围内查找这个变量。假设在循环中使用map,可能会出现效率问题。所以应该做成局部作用域:上面的使用函数创建局部作用域,也可以使用ES6块级作用域。由于变量map是在当前局部作用域直接命中的,所以不需要查找下一级作用域(这里是全局作用域),局部作用域的查找速度非常快。同时,直接在全局范围内定义变量会污染window对象。(2)不要滥用闭包闭包的作用是让子级作用域可以使用其父级作用域中的变量,而这些变量在不同的闭包中是不可见的。这就导致了在查找变量时,如果在当前作用域中找不到,就必须在其父作用域中逐层查找,直到找到,否则在全局作用域中还没有找到。.所以闭包嵌套得越深,变量查找的时间就越长。如下:functiongetResult(count){count++;functionprocess(){varfactor=2;returncount*factor-5;}returnprocess();}以上代码定义了一个过程函数,其中count变量的查找时间高于局部因子变量。其实这里不适合用闭包,可以直接把count传给进程:functiongetResult(count){count++;functionprocess(count){varfactor=2;returncount*factor-5;}returnprocess(count);}这样的countlookupTime和factor一样,直接命中当前作用域。这启发我们,如果一个全局变量需要经常使用,我们可以使用一个局部变量来缓存它,如下:varurl="";if(window.location.protocal==="https:"){url="wss://xxx.com"+window.location.pathname+window.location.search;}window.location对象经常使用,可以先缓存起来:varurl="";varlocation=window.location;if(location.protocal==="https:"){url="wss://xxx.com"+location.pathname+location.search;}变成局部变量,所以搜索速度会明显加快对于全局搜索,代码也可以少写。3、避免使用==这里大家可能会有疑惑,有的人喜欢用==,有的人喜欢用===,每个人的风格不一样,你为什么要强迫别人用===呢?习惯上用=有=的人不能只因为==比===少了一次击键。为什么不提倡使用==?(1)如果判断变量的类型,那么就不用==了,如下:if(typeofnum!="undefined"){}varnum=parseInt(value);if(num==10){}上面两个例子是有一定类型的,一个是字符串,一个是整数。不用==,直接用===就可以了。(2)如果不确定类型,那么你应该手动做一个类型转换,而不是让别人或者你以后猜测有类型转换,如下:vartotalPage="5";if(parseInt(totalPage)===1){}(3)使用==让JSLint检查失败:if(a==b){}以下JSLint输出:Expected'==='andinsteadsaw'=='.if(a==b){(4)而使用==可能会导致一些奇怪的现象,可能会在代码中埋下隐患:null==undefined//true''=='0'//false0==''//true0=='0'//true''==0//truenewString("abc")=="abc"//truenewBool??ean(true)==true//truetrue==1//true上面使用时比较为false===,这样比较合理。比如第一点,null其实等于undefined,这就特别奇怪了,因为null和undefined是两个不相干的值,null应该作为一个初始化的空值,而undefined用来检查一个变量是否是不明确的。这类似于第1点引入强类型的思路。4、如果组合表达式可以用1个代码实现5个代码的功能,那么1个代码的执行效率会更高,可读性可能会更好(1)用三元运算符代替简单的if-else如上面的getPrice函数:functiongetPrice(count){if(count<0)return-1;elsereturncount*100;}可以改成:functiongetPrice(count){returncount<0?return-1:count*100;这看起来比编写if-else干净得多。当然,如果你写if-else,压缩工具也会帮你改成三元运算符的形式:functiongetPrice(e){return0>e?-1:100*e}(2)等yesUsing赋值运算表达式会返回赋值,执行顺序是从右到左,如下:overtime=favhouse=listingDetail={...}有时你会看到有人这样写:varage=0;if((age=+form.age.value)>=18){console.log("你是成年人");}else{consoe.log("孩子们,你还有"+(18-age)+"我是anadult");}也是用赋值表达式返回一个值,在if里赋值的时候用它的返回值做判断,然后else里已经有值了。上面的+号将字符串转换为整数。(3)自增使用自增还可以简化代码。如下,每发送一条消息,localMsgId都会加1:chatService.sendMessage(localMsgId++,msgContent);5.减少幻数。比如在一个文件的第800行,弹出一句话:dialogHandler.showQuestionNaire("seller","sell",5,true);会让人很疑惑,上面的四个常量代表什么,如果不去查看那个函数的变量说明,我是无法快速理解这些常量是干什么用的?这些意义不明的常量被称为“幻数”。所以最好给这些常量起个名字,尤其是在一些比较关键的地方。比如上面的代码可以改成:varnaireType="seller",dialogType="sell",questionsCount=5,reloadWindow=true;naireHandler.showNaire(naireType,dialogType,questionsCount,reloadWindow);所以意思很明显。6、使用ES6简化代码ES6已经发展多年,兼容性一直很好。正确使用可以使代码更加简洁优雅。(1)使用箭头函数代替小函数。用到小函数的场景有很多。如果写一个函数,至少需要写3行代码,但是可以在一行中使用箭头函数。例如数组从大到小排序:varnums=[4,8,1,9,0];nums.sort(function(a,b){returnb-a;});//输出[9,8,4,1,0]如果使用箭头函数,排序只需要一行即可:varnums=[4,8,1,9,0];``nums.sort(a,b=>b-a);代码看起来简洁多了,经常有setTimeouts,只需要执行一行代码就可以了,但是写一个函数总感觉有点麻烦,而且使用字符串的方法也不是很好,所以也很这种情况下使用箭头函数很方便:setTimeout(()=>console.log("hi"),3000)箭头函数在C++/Java等语言中被称为Lambda表达式。Ruby早有这种语法形式,后来的C++/Java也实现了这种语法。当然,箭头函数或者Lambda表达式不仅适用于这种单行代码,也适用于多行代码,只是单行时其优势更加明显。(2)使用ES6class虽然ES6class和prototypeusingfunction在本质上是一样的,但是它们都使用了prototype。但是使用class可以减少代码量,同时让代码看起来更高大上。使用函数需要写这么多:functionPerson(name,age){this.name=name;this.age=age;}Person.prototype.addAge=function(){this.age++;};Person.prototype.setName=function(名字){this.name=名字;};使用类代码看起来简洁易懂:classPerson{constructor(name,age){this.name=name;this.age=age;}addAge(){this.age++;}setName(name){this.name=name;}}和class也可以很方便的实现继承和静态成员函数,就不用你了需要通过一些技巧才能自己实现。(3)字符串拼接前,需要使用+号拼接:vartpl='
