首页

科技
手机搜狐
SOHU.COM

简洁的javascript编码(一)--变量、函数

IMWeb前端团队
2017-02-17
+关注

一、变量

Bad

Good

constcurrentDate = moment().format( 'YYYY/MM/DD');

通常我们读代码比写得多,所以代码都可读性以及可搜索性非常重要。如果对变量不负于语义化、易理解的名字,代码的阅读者将非常痛苦。buddy.js以及ESLint能够帮助我们定位未命名的常量。

Bad

Good

// 通过大写常量来定义.constMILLISECONDS_IN_A_DAY = 86400000;setTimeout(blastOff, MILLISECONDS_IN_A_DAY);

Bad

Good

constaddress = ' OneInfinite Loop, Cupertino 95014'; constcityZipCodeRegex = /^[^,]+[,s]+(.+?)s*( d{5})?$/; const[, city, zipCode] = address. match(cityZipCodeRegex) || [];saveCityZipCode(city, zipCode);

展开剩余90%

在遍历时,避免简单无意义的变量命名

Bad

Good

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

如果你的类名/对象名已经能够表述某些信息,那么在类/对象名的属性中就不需要重复命名。

Bad

Good

constCar = { make: 'Honda', model: 'Accord', color: 'Blue'}; functionpaintCar(car){ car.color = 'Red';}

Bad

Good

functioncreateMicrobrewery(breweryName = 'Hipster Brew Co.'){ // ...} 二、函数

Bad:

Good:

functioncreateMenu({ title, body, buttonText, cancellable}) { // ...} createMenu({ title: 'Foo', body: 'Bar', buttonText: 'Baz', cancellable: true});

这是目前为止软件工程的最重要原则之一。但赋予函数太多职责,他们将很难被组合,测试以及推导。而如果你保证函数的单一职责性质,那么其重构难度将会降低、代码可读性也会更好。

Bad

Good

functionemailClients(clients){clients .filter (isClientActive).forEach (email);} functionisClientActive(client){const clientRecord = database. lookup(client); return clientRecord.isActive ();}

Bad

Good:

functionaddMonthToDate(month, date) { // ...} constdate = newDate();addMonthToDate( 1, date);

类似与函数单一职责,当你的函数超过一层抽象时,说明你的函数做太多事情了。通过拆分函数让你的代码更加可复用以及测试。

Bad:

Good:

functiontokenize(code){ constREGEXES = [ // ...]; conststatements = code.split( ' '); consttokens = []; REGEXES. forEach((REGEX) => { statements. forEach((statement) => { tokens.push( /* ... */); }); }); returntokens;} functionlexer(tokens){ constast = []; tokens. forEach((token) => { ast.push( /* ... */); }); returnast;} functionparseBetterJSAlternative(code){ consttokens = tokenize(code); constast = lexer(tokens); ast. forEach((node) => { // parse...});}

你是否尽可能地在避免重复代码呢?在你将要修改某处逻辑时,重复代码将会非常恶心导致你不止修改一处地方。

Bad:

Good:

functionshowEmployeeList(employees){employees.forEach ((employee)=> { const expectedSalary = employee.calculateExpectedSalary(); const experience = employee.getExperience(); let portfolio = employee.getGithubLink(); if (employee.type === 'manager'){ portfolio = employee.getMBAProjects(); } const data = { expectedSalary, experience, portfolio }; render(data); });}

Bad:

Good:

const menuConfig = { title: 'Order', // User did notinclude 'body'key buttonText: 'Send', cancellable: true}; functioncreateMenu(config){ config = Object.assign({ title: 'Foo', body: 'Bar', buttonText: 'Baz', cancellable: true}, config); // config 现在等于: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} // ...}createMenu(menuConfig);

Bad:

Good:

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

如果某个函数除了接收输入值与返回值之外还做了其他事,那么就称其具有副作用。典型的副作用譬如写文件、修改某些全局变量、修改内存参数等等。

在编程中我们不可避免的需要产生副作用,譬如上面例子中我们需要写入到某个外部文件。而你应当做的就是将所有的写文件操作由某个服务统一处理,而不应该将写文件的操作分散到数个类或者函数中。这一点最大的优势在于避免了不同对象之间共享状态。

Bad:

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:

const addItemToCart = (cart, item)=>{ return[...cart, { item, date : Date.now() }];};

由于你的修改导致污染全局变量,可能导致另外一个库的使用者在不知情的情况下出现生产环境异常。例如,你想扩展Array方法diff,用于区分2个数组的不同。你可能通过Array的原型链扩展,但可能导致其他库的的diff方法失效,例如找出一个数组第一跟最后一个元素的不同的方法。所以这就是为什么更建议通过ES6的classes,并且使用继承方式去添加新的功能函数。Bad:

Good:

classSuperArrayextendsArray{diff(comparisonArray) { const hash = newSet(comparisonArray); returnthis.filter(elem => !hash.has(elem)); }}

Bad:

Good:

const programmerOutput = [ { name: 'Uncle Bobby', linesOfCode: 500}, { name: 'Suzie Q', linesOfCode: 1500}, { name: 'Jimmy Gosling', linesOfCode: 150}, { name: 'Gracie Hopper', linesOfCode: 1000}];const INITIAL_VALUE = 0;const totalOutput = programmerOutput .map( (programmer)=>programmer.linesOfCode) .reduce( (acc, linesOfCode)=>acc + linesOfCode, INITIAL_VALUE);

Bad:

Good:

functionshouldShowSpinner(fsm, listNode){return fsm.state === 'fetching' && isEmpty (listNode);} if(shouldShowSpinner(fsmInstance, listNodeInstance)){ // ...}

Bad:

Good:

functionisDOMNodePresent(node){// ...} if(isDOMNodePresent(node)){ // ...}

这似乎听起来是一个不可能的任务,没有if条件选择语句的话又该如何编程呢?在这里我们推荐使用多态性来达成这一目标,因为如果在函数或类中嵌入过多的if语句,会导致该函数或者类破坏单一职责原则。

Bad:

Good:

classAirplane{// ...} classBoeing777extendsAirplane{// ...getCruisingAltitude() { returnthis.getMaxAltitude() - this.getPassengerCount(); }} classAirForceOneextendsAirplane{// ...getCruisingAltitude() { returnthis.getMaxAltitude(); }} classCessnaextendsAirplane{// ...getCruisingAltitude() { returnthis.getMaxAltitude() - this.getFuelExpenditure(); }}

现代浏览器已经在运行时做了很多的优化,因此很多时候如果我们要遵循那些流传已久的优化策略不过是浪费时间。可以参考这个来获取建议的优化要点。

Bad:

// On old browsers, eachiteration withuncached `list. length` would be costly // because of `list.length` recomputation. In modern browsers, this is optimized.// 在老的浏览器,每次循环都会去计算list.lenth造成消耗// 但在现在浏览器,已经被优化了for(let i = 0, len= list. length; i < len; i++) { // ...}

Good:

for (let i = 0; i < list.length; i++){ // ...}

原文连接

帅哥为什么要拒绝美女的微信?

声明:本文由入驻搜狐号作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。

网站地图

用户反馈 合作
Copyright © 2018 Sohu.com