ES6——编程风格
编程风格1、块级作用域1.1、Iet取代var1.2、全局常量和线程安全1.3、严格模式2、字符串3、解构赋值4、对象5、数组6、函数7、Map结构8、Class9、模块10、ESLint的使用1、块级作用域1.1、Iet取代varES6提出了两个新的声明变量的命令let和const。其中let完全可以取代var因为两者语义相同而且let没有副作用。use strict;if(true){letxhello;}for(leti0;i10;i){console.log(i);}上面的代码如果用var替代let实际上就声明了一个全局变量这显然不是本意。变量应该只在其声明的代码块内有效var命令做不到这一点。var命令存在变量提升效用let命令没有这个问题。use strict;if(true){console.log(x);//ReferenceErrorletxhello;}上面的代码如果使用var替代let那么console.log那一行就不会报错而是会输出undefined因为变量声明会提升到代码块的头部。这违反了变量先声明后使用的原则。所以建议不再使用var命令而是使用let命令取代。1.2、全局常量和线程安全在let和const之间建议优先使用const尤其是在全局环境不应该设置变量只应设置常量。这符合函数式编程思想有利于将来的分布式运算。//badleta1,b2,c3;//goodconsta1;constb2;constc3;//bestconst[a,b,c][1,2,3];const声明常量还有两个好处一是阅读代码的人立刻会意识到不应该修改这个值二是防止了无意间修改变量值导致错误。所有的函数都应该设置为常量。let表示的变量只应出现在单线程运行的代码中不能是多线程共享的这样有利于保证线程安全。1.3、严格模式V8引擎只在严格模式下支持let和const。结合前两点这实际上意味着将来所有的编程都是针对严格模式的。2、字符串静态字符串一律使用单引号或反引号不使用双引号。动态字符串使用反引号。//badconstafoobar;constbfooabar;//acceptableconstcfoobar;//goodconstafoobar;constbfoo${a}bar;constcfoobar;3、解构赋值使用数组成员对变量赋值优先使用解构赋值。constarr[1,2,3,4];//badconstfirstarr[0];constsecondarr[1];//goodconst[first,second]arr;函数的参数如果是对象的成员优先使用解构赋值。//badfunctiongetFullName(user){constfirstNameuser.firstName;constlastNameuser.lastName;}//goodfunctiongetFullName(obj){const{firstName,lastName}obj;}//bestfunctiongetFullName({firstName,lastName}){}如果函数返回多个值优先使用对象的解构赋值而不是数组的解构赋值。这样便于以后添加返回值以及更改返回值的顺序。//badfunctionprocessInput(input){return[screenLeft,right,top,bottom];}//goodfunctionprocessInput(input){return{left,right,top,bottom};}const{left,right}processInput(input);4、对象单行定义的对象最后一个成员不以逗号结尾。多行定义的对象最后一个成员以逗号结尾。//badconsta{k1:v1,k2:v2,};constb{k1:v1,k2:v2};//goodconsta{k1:v1,k2:v2};constb{k1:v2,k2:v2,};对象尽量静态化一旦定义就不得随意添加新的属性。如果添加属性不可避免要使用Object.assign方法。//badconsta{};a.x3;//if reshape unavoidableconsta{};Object.assign(a,{x:3});//goodconsta{x:null};a.x3;如果对象的属性名是动态的可以在创造对象时使用属性表达式定义。//badconstobj{id:5,name:San Francisco,};obj[getKey(enabled)]true;//goodconstobj{id:5,name:San Francisco,[getKey(enabled)]:true,};上面的代码中对象obj的最后一个属性名需要计算得到。这时最好采用属性表达式在新建obj时将该属性与其他属性定义在一起。这样一来所有属性就在一个地方定义了。另外对象的属性和方法尽量采用简洁表达法这样易于描述和书写。letrefsome value;//badconstatom{ref:ref,value:1,addValue:function(value){returnatom.valuevalue;},};//goodconstatom{ref,value:1,addValue(value){returnatom.valuevalue;}};5、数组使用扩展运算符(…)复制数组。//badconstlenitems.length;constitemsCopy[];leti;for(i0;ilen;i){itemsCopy[i]items[i];}//goodconstitemsCopy[...items];使用Array.from方法将类似数组的对象转为数组。constfoodocument.querySelectorAll(.foo);constnodesArray.from(foo);6、函数立即执行函数可以写成箭头函数的形式。((){console.log(Welcome to the Internet.);})();那些需要使用函数表达式的场合尽量用箭头函数代替。因为这样更简洁而且绑定了this。//bad[1,2,3].map(function(x){returnx*x;});//good[1,2,3].map((x){returnx*x;});箭头函数取代Function.prototype.bind不应再用self/_this/that绑定this。//badconstselfthis;constboundMethodfunction(...params){returnmethod.apply(self,params);}//acceptableconstboundMethodmethod.bind(this);//bestconstboundMethod(...params)method.apply(this,params);简单的、单行的、不会复用的函数建议采用箭头函数。如果函数体较为复杂行数较多还是应该采用传统的函数写法。所有配置项都应该集中在一个对象放在最后一个参数布尔值不可以直接作为参数。//badfunctiondivide(a,b,optionfalse){}//goodfunctiondivide(a,b,{optionfalse}{}){}不要在函数体内使用arguments变量使用rest运算符(…)代替。因为rest运算符显式表明你想要获取参数而且arguments是一个类似数组的对象而rest运算符可以提供一个真正的数组。//badfunctionconcatenateAll(){constargsArray.prototype.slice.call(arguments);returnargs.join();}//goodfunctionconcatenateAll(...args){returnargs.join();}使用默认值语法设置函数参数的默认值。//badfunctionhandleThings(opts){optsopts||{};}//goodfunctionhandleThings(opts{}){}7、Map结构注意区分Object和Map只有模拟实体对象时才使用Object。如果只是需要key:value的数据结构则使用Map。因为Map有内建的遍历机制。letmapnewMap(arr);for(letkeyofmap.keys()){console.log(key);}for(letvalueofmap.values()){console.log(value);}for(letitemofmap.entries()){console.log(item[0],item[1]);}8、Class总是用Class取代需要prototype的操作。因为Class的写法更简洁更易于理解。//badfunctionQueue(contents[]){this._queue[...contents];}Queue.prototype.popfunction(){constvaluethis._queue[0];this._queue.splice(0,1);returnvalue;}//goodclassQueue{constructor(contents[]){this._queue[...contents];}pop(){constvaluethis._queue[0];this._queue.splice(0,1);returnvalue;}}使用extends实现继承因为这样更简单不会有破坏instanceof运算的危险。//badconstinheritsrequire(inherits);constinHeritsrequire(inherits);functionPeekableQueue(constents){Queue.apply(this,contents);}inherits(PeekableQueue,Queue);PeekableQueue.prototype.peekfunction(){returnthis._queue[0];}//goodclassPeekableQueueextendsQueue{peek(){returnthis._queue[0];}}9、模块Module语法是JavaScript模块的标准写法要坚持使用这种写法。使用import取代require。//badconstmoduleArequire(moduleA);constfunc1moduleA.func1;constfunc2moduleA.func2;//goodimport{func1,func2}frommoduleA;使用export取代module.exports。//CommonJS的写法letReactrequire(react);letBreadcrumbsReact.createClass({render(){returnnav/;}});module.exportsBreadcrumbs;//ES6的写法importReactfromreact;constBreadcrumbsReact.createClass({render(){returnnav/;}});exportdefaultBreadcrumbs如果模块只有一个输出值就使用export default如果模块有多个输出值就不使用export default不要export default与普通的export同时使用。不要在模块输入中使用通配符。因为这样可以确保模块中有一个默认输出(export default)。//badimport*asmyObject./importModule;//goodimportmyObjectfrom./importModule;如果模块默认输出一个函数函数名的首字母应该小写。functionmakeStyleGuide(){}exportdefaultmakeStyleGuide;如果模块默认输出一个对象对象名的首字母应该大写。cosnt StyleGuide{es6:{}};exportdefaultStyleGuide;10、ESLint的使用ESLint是一个语法规则和代码风格的检查工具可用于保证写出语法正确、风格统一的代码。首先安装ESLint。$npmi-geslint然后安装Airbnb语法规则。$npmig eslint-config-airbnb最后在项目的根目录下新建.eslintrc文件配置ESLint。{extends:eslint-config-airbnb}现在就可以检查当前项目的代码是否符合预设的规则。index.js文件的代码如下。letunusuedI have no purpose!;functiongreet(){letmessageHello, World!;alert(message);}greet();使用ESLint检查这个文件。$ eslint index.js
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2511232.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!