让前端飞Web前端之路Web 前端开发

如何写出干净整洁的JavaScript

2019-11-07  本文已影响0人  前端小咖

变量

使用有意义和可理解的变量名

bad:

constyyyymmdstr = moment().format("YYYY/MM/DD");复制代码

good:

constcurrentDate = moment().format("YYYY/MM/DD");复制代码

使用具有解释性的变量

Bad:

constaddress ="One Infinite Loop, Cupertino 95014";constcityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;saveCityZipCode(  address.match(cityZipCodeRegex)[1],  address.match(cityZipCodeRegex)[2]);复制代码

Good:

constaddress ="One Infinite Loop, Cupertino 95014";constcityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;const[, city, zipCode] = address.match(cityZipCodeRegex) || [];saveCityZipCode(city, zipCode);复制代码

避免使用隐式映射

Bad:

constlocations = ["Austin","New York","San Francisco"];locations.forEach(l => {  doStuff();  doSomeOtherStuff();// ...// ...// ...// Wait, what is `l` for again?dispatch(l);});复制代码

Good:

constlocations = ["Austin","New York","San Francisco"];locations.forEach(location => {  doStuff();  doSomeOtherStuff();// ...// ...// ...dispatch(location);});复制代码

不要添加不必要的内容

Bad:

constCar = {  carMake:"Honda",  carModel:"Accord",  carColor:"Blue"};functionpaintCar(car){  car.carColor ="Red";}复制代码

Good:

constCar = {  make:"Honda",  model:"Accord",  color:"Blue"};functionpaintCar(car){  car.color ="Red";}复制代码

函数

函数参数因少于等于两个

限制你的函数参数数量是非常有必要的,这可以让你更容易测试你的函数。理想情况下函数参数等于小于两个,如果超过了两个,只能证明你的函数做的太多了,违背了单一功能的设计原则。

Bad:

functioncreateMenu(title, body, buttonText, cancellable){// ...}复制代码

Good:

functioncreateMenu({title,body,buttonText,cancellable}) {// ...}createMenu({title:"Foo",body:"Bar",buttonText:"Baz",cancellable: true});复制代码

不要使用标志作为函数的参数

函数功能应该保持单一功能。

bad

functioncreateFile(name, temp){if(temp) {    fs.create(`./temp/${name}`);  }else{    fs.create(name);  }}复制代码

good

functioncreateFile(name){  fs.create(name);}functioncreateTempFile(name){  createFile(`./temp/${name}`);}复制代码

使用默认参数

Bad:

functioncreateMicrobrewery(name){constbreweryName = name ||"Hipster Brew Co.";// ...}复制代码

Good:

functioncreateMicrobrewery(name ="Hipster Brew Co."){// ...}复制代码

函数应该只处理同一抽象级别的功能

当你的函数要处理多个层级的功能,那你的函数就太复杂了。你应该把函数分割成各个层级以方便复用和测试。

Bad:

functionparseBetterJSAlternative(code){constREGEXES = [// ...];conststatements = code.split(" ");consttokens = [];  REGEXES.forEach(REGEX => {    statements.forEach(statement => {// ...});  });constast = [];  tokens.forEach(token => {// lex...});  ast.forEach(node => {// parse...});}复制代码

Good:

functionparseBetterJSAlternative(code){consttokens = tokenize(code);constsyntaxTree = parse(tokens);  syntaxTree.forEach(node => {// parse...});}functiontokenize(code){constREGEXES = [// ...];conststatements = code.split(" ");consttokens = [];  REGEXES.forEach(REGEX => {    statements.forEach(statement => {      tokens.push(/* ... */);    });  });returntokens;}functionparse(tokens){constsyntaxTree = [];  tokens.forEach(token => {    syntaxTree.push(/* ... */);  });returnsyntaxTree;}复制代码

避免副作用

一个函数会产生副作用除非它只读取参数然后返回另外一个参数

Bad:

// Global variable referenced by following function.// If we had another function that used this name, now it'd be an array and it could break it.letname ="Ryan McDermott";functionsplitIntoFirstAndLastName(){  name = name.split(" ");}splitIntoFirstAndLastName();console.log(name);// ['Ryan', 'McDermott'];复制代码

Good:

functionsplitIntoFirstAndLastName(name){returnname.split(" ");}constname ="Ryan McDermott";constnewName = splitIntoFirstAndLastName(name);console.log(name);// 'Ryan McDermott';console.log(newName);// ['Ryan', 'McDermott'];复制代码

Bad:

constaddItemToCart = (cart, item) => {  cart.push({ item,date:Date.now() });};复制代码

Good:

constaddItemToCart =(cart, item) =>{return[...cart, { item,date:Date.now() }];};复制代码

封装条件语句

Bad:

if(fsm.state ==="fetching"&& isEmpty(listNode)) {// ...}复制代码

Good:

functionshouldShowSpinner(fsm, listNode){returnfsm.state ==="fetching"&& isEmpty(listNode);}if(shouldShowSpinner(fsmInstance, listNodeInstance)) {// ...}复制代码

避免使用否定语句

Bad:

functionisDOMNodeNotPresent(node){// ...}if(!isDOMNodeNotPresent(node)) {// ...}复制代码

Good:

functionisDOMNodePresent(node){// ...}if(isDOMNodePresent(node)) {// ...}复制代码

对象和数据结构

使用setters跟getters

当你想做的不仅仅是获取一个对象属性,你不需要查找和更改代码库中的每个访问器。

使在执行集合时添加验证变得简单。

封装内部表示。

在获取和设置时易于添加日志记录和错误处理。

可以延迟加载对象的属性,例如从服务器获取。

Bad:

functionmakeBankAccount(){// ...return{    balance:0// ...};}constaccount = makeBankAccount();account.balance =100;复制代码

Good:

functionmakeBankAccount(){// this one is privateletbalance =0;// a "getter", made public via the returned object belowfunctiongetBalance(){returnbalance;  }// a "setter", made public via the returned object belowfunctionsetBalance(amount){// ... validate before updating the balancebalance = amount;  }return{// ...getBalance,    setBalance  };}constaccount = makeBankAccount();account.setBalance(100);复制代码

使用链式调用

Bad:

classCar{constructor(make, model, color) {this.make = make;this.model = model;this.color = color;  }  setMake(make) {this.make = make;  }  setModel(model) {this.model = model;  }  setColor(color) {this.color = color;  }  save() {    console.log(this.make,this.model,this.color);  }}const car = new Car("Ford","F-150","red");car.setColor("pink");car.save();复制代码

Good:

classCar{constructor(make, model, color) {this.make = make;this.model = model;this.color = color;  }  setMake(make) {this.make = make;//NOTE:Returning this for chainingreturnthis;  }  setModel(model) {this.model = model;//NOTE:Returning this for chainingreturnthis;  }  setColor(color) {this.color = color;//NOTE:Returning this for chainingreturnthis;  }  save() {    console.log(this.make,this.model,this.color);//NOTE:Returning this for chainingreturnthis;  }}const car = new Car("Ford","F-150","red").setColor("pink").save();复制代码

如果对于学习编程有很多疑惑,没有思路,不知道如何有效率的学习,可以添加我的前端交流学习群 895757445,需要最新系统的学习教程也可以管我要。做了很多年开发,对于学习方式,如何提高自己的技术有一定的经验,术业有专攻,多跟有经验的人交流学习,对这个行业信息了解的多,职业发展的空间就越大

上一篇 下一篇

猜你喜欢

热点阅读