diff --git a/README.md b/README.md index 94e7fa2c..db58b0d6 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,12 @@ improvement. Beat up the code instead! **Bad:** ```javascript -var yyyymmdstr = moment().format('YYYY/MM/DD'); +const yyyymmdstr = moment().format('YYYY/MM/DD'); ``` **Good**: ```javascript -var yearMonthDay = moment().format('YYYY/MM/DD'); +const yearMonthDay = moment().format('YYYY/MM/DD'); ``` **[⬆ back to top](#table-of-contents)** @@ -95,16 +95,16 @@ Make your names searchable. **Bad:** ```javascript // What the heck is 525600 for? -for (var i = 0; i < 525600; i++) { +for (let i = 0; i < 525600; i++) { runCronJob(); } ``` **Good**: ```javascript -// Declare them as capitalized `var` globals. -var MINUTES_IN_A_YEAR = 525600; -for (var i = 0; i < MINUTES_IN_A_YEAR; i++) { +// Declare them as capitalized `const` globals. +const MINUTES_IN_A_YEAR = 525600; +for (let i = 0; i < MINUTES_IN_A_YEAR; i++) { runCronJob(); } ``` @@ -132,7 +132,7 @@ Explicit is better than implicit. **Bad:** ```javascript -var locations = ['Austin', 'New York', 'San Francisco']; +const locations = ['Austin', 'New York', 'San Francisco']; locations.forEach((l) => { doStuff(); doSomeOtherStuff(); @@ -146,7 +146,7 @@ locations.forEach((l) => { **Good**: ```javascript -var locations = ['Austin', 'New York', 'San Francisco']; +const locations = ['Austin', 'New York', 'San Francisco']; locations.forEach((location) => { doStuff(); doSomeOtherStuff(); @@ -164,7 +164,7 @@ variable name. **Bad:** ```javascript -var Car = { +const Car = { carMake: 'Honda', carModel: 'Accord', carColor: 'Blue' @@ -177,7 +177,7 @@ function paintCar(car) { **Good**: ```javascript -var Car = { +const Car = { make: 'Honda', model: 'Accord', color: 'Blue' @@ -194,7 +194,7 @@ function paintCar(car) { **Bad:** ```javascript function createMicrobrewery(name) { - var breweryName; + let breweryName; if (name) { breweryName = name; } else { @@ -206,7 +206,7 @@ function createMicrobrewery(name) { **Good**: ```javascript function createMicrobrewery(name) { - var breweryName = name || 'Hipster Brew Co.' + const breweryName = name || 'Hipster Brew Co.' } ``` **[⬆ back to top](#table-of-contents)** @@ -237,7 +237,7 @@ function createMenu(title, body, buttonText, cancellable) { **Good**: ```javascript -var menuConfig = { +const menuConfig = { title: 'Foo', body: 'Bar', buttonText: 'Baz', @@ -263,7 +263,7 @@ this guide other than this, you'll be ahead of many developers. ```javascript function emailClients(clients) { clients.forEach(client => { - let clientRecord = database.lookup(client); + const clientRecord = database.lookup(client); if (clientRecord.isActive()) { email(client); } @@ -286,7 +286,7 @@ function emailClientIfNeeded(client) { } function isClientActive(client) { - let clientRecord = database.lookup(client); + const clientRecord = database.lookup(client); return clientRecord.isActive(); } ``` @@ -300,7 +300,7 @@ function dateAdd(date, month) { // ... } -let date = new Date(); +const date = new Date(); // It's hard to to tell from the function name what is added dateAdd(date, 1); @@ -312,7 +312,7 @@ function dateAddMonth(date, month) { // ... } -let date = new Date(); +const date = new Date(); dateAddMonth(date, 1); ``` **[⬆ back to top](#table-of-contents)** @@ -325,19 +325,19 @@ testing. **Bad:** ```javascript function parseBetterJSAlternative(code) { - let REGEXES = [ + const REGEXES = [ // ... ]; - let statements = code.split(' '); - let tokens; + const statements = code.split(' '); + const tokens = []; REGEXES.forEach((REGEX) => { statements.forEach((statement) => { // ... }) }); - let ast; + const ast = []; tokens.forEach((token) => { // lex... }); @@ -351,15 +351,15 @@ function parseBetterJSAlternative(code) { **Good**: ```javascript function tokenize(code) { - let REGEXES = [ + const REGEXES = [ // ... ]; - let statements = code.split(' '); - let tokens; + const statements = code.split(' '); + const tokens = []; REGEXES.forEach((REGEX) => { statements.forEach((statement) => { - // ... + tokens.push( // ... ); }) }); @@ -367,17 +367,17 @@ function tokenize(code) { } function lexer(tokens) { - let ast; + const ast = []; tokens.forEach((token) => { - // lex... + ast.push( // ... ); }); return ast; } function parseBetterJSAlternative(code) { - let tokens = tokenize(code); - let ast = lexer(tokens); + const tokens = tokenize(code); + const ast = lexer(tokens); ast.forEach((node) => { // parse... }) @@ -396,10 +396,10 @@ generic functions quite easy. Take advantage of that! ```javascript function showDeveloperList(developers) { developers.forEach(developers => { - var expectedSalary = developer.calculateExpectedSalary(); - var experience = developer.getExperience(); - var githubLink = developer.getGithubLink(); - var data = { + const expectedSalary = developer.calculateExpectedSalary(); + const experience = developer.getExperience(); + const githubLink = developer.getGithubLink(); + const data = { expectedSalary: expectedSalary, experience: experience, githubLink: githubLink @@ -411,10 +411,10 @@ function showDeveloperList(developers) { function showManagerList(managers) { managers.forEach(manager => { - var expectedSalary = manager.calculateExpectedSalary(); - var experience = manager.getExperience(); - var portfolio = manager.getMBAProjects(); - var data = { + const expectedSalary = manager.calculateExpectedSalary(); + const experience = manager.getExperience(); + const portfolio = manager.getMBAProjects(); + const data = { expectedSalary: expectedSalary, experience: experience, portfolio: portfolio @@ -429,17 +429,16 @@ function showManagerList(managers) { ```javascript function showList(employees) { employees.forEach(employee => { - var expectedSalary = employee.calculateExpectedSalary(); - var experience = employee.getExperience(); - var portfolio; + const expectedSalary = employee.calculateExpectedSalary(); + const experience = employee.getExperience(); + + let portfolio = employee.getGithubLink(); if (employee.type === 'manager') { portfolio = employee.getMBAProjects(); - } else { - portfolio = employee.getGithubLink(); } - var data = { + const data = { expectedSalary: expectedSalary, experience: experience, portfolio: portfolio @@ -474,7 +473,7 @@ function writeForumComment(subject = 'No subject', body = 'No text') { **Bad:** ```javascript -var menuConfig = { +const menuConfig = { title: null, body: 'Bar', buttonText: null, @@ -494,7 +493,7 @@ createMenu(menuConfig); **Good**: ```javascript -var menuConfig = { +const menuConfig = { title: 'Order', // User did not include 'body' key buttonText: 'Send', @@ -564,7 +563,7 @@ be happier than the vast majority of other programmers. ```javascript // 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. -var name = 'Ryan McDermott'; +let name = 'Ryan McDermott'; function splitIntoFirstAndLastName() { name = name.split(' '); @@ -581,8 +580,8 @@ function splitIntoFirstAndLastName(name) { return name.split(' '); } -var name = 'Ryan McDermott' -var newName = splitIntoFirstAndLastName(name); +const name = 'Ryan McDermott' +const newName = splitIntoFirstAndLastName(name); console.log(name); // 'Ryan McDermott'; console.log(newName); // ['Ryan', 'McDermott']; @@ -603,14 +602,14 @@ would be much better to just use ES6 classes and simply extend the `Array` globa **Bad:** ```javascript Array.prototype.diff = function(comparisonArray) { - var values = []; - var hash = {}; + const values = []; + const hash = {}; - for (var i of comparisonArray) { + for (let i of comparisonArray) { hash[i] = true; } - for (var i of this) { + for (let i of this) { if (!hash[i]) { values.push(i); } @@ -628,14 +627,14 @@ class SuperArray extends Array { } diff(comparisonArray) { - var values = []; - var hash = {}; + const values = []; + const hash = {}; - for (var i of comparisonArray) { + for (let i of comparisonArray) { hash[i] = true; } - for (var i of this) { + for (let i of this) { if (!hash[i]) { values.push(i); } @@ -671,9 +670,9 @@ const programmerOutput = [ } ]; -var totalOutput = 0; +let totalOutput = 0; -for (var i = 0; i < programmerOutput.length; i++) { +for (let i = 0; i < programmerOutput.length; i++) { totalOutput += programmerOutput[i].linesOfCode; } ``` @@ -696,7 +695,7 @@ const programmerOutput = [ } ]; -var totalOutput = programmerOutput +const totalOutput = programmerOutput .map((programmer) => programmer.linesOfCode) .reduce((acc, linesOfCode) => acc + linesOfCode, 0); ``` @@ -872,14 +871,14 @@ they are fixed if they can be. // On old browsers, each iteration would be costly because `len` would be // recomputed. In modern browsers, this is optimized. -for (var i = 0, len = list.length; i < len; i++) { +for (let i = 0, len = list.length; i < len; i++) { // ... } ``` **Good**: ```javascript -for (var i = 0; i < list.length; i++) { +for (let i = 0; i < list.length; i++) { // ... } ``` @@ -900,7 +899,7 @@ function newRequestModule(url) { // ... } -var req = newRequestModule; +const req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); ``` @@ -911,7 +910,7 @@ function newRequestModule(url) { // ... } -var req = newRequestModule; +const req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); ``` **[⬆ back to top](#table-of-contents)** @@ -942,7 +941,7 @@ class BankAccount { } } -let bankAccount = new BankAccount(); +const bankAccount = new BankAccount(); // Buy shoes... bankAccount.balance = bankAccount.balance - 100; @@ -963,7 +962,7 @@ class BankAccount { } } -let bankAccount = new BankAccount(); +const bankAccount = new BankAccount(); // Buy shoes... bankAccount.withdraw(100); @@ -977,7 +976,7 @@ This can be accomplished through closures (for ES5 and below). **Bad:** ```javascript -var Employee = function(name) { +const Employee = function(name) { this.name = name; } @@ -985,7 +984,7 @@ Employee.prototype.getName = function() { return this.name; } -var employee = new Employee('John Doe'); +const employee = new Employee('John Doe'); console.log('Employee name: ' + employee.getName()); // Employee name: John Doe delete employee.name; console.log('Employee name: ' + employee.getName()); // Employee name: undefined @@ -993,7 +992,7 @@ console.log('Employee name: ' + employee.getName()); // Employee name: undefined **Good**: ```javascript -var Employee = (function() { +const Employee = (function() { function Employee(name) { this.getName = function() { return name; @@ -1003,7 +1002,7 @@ var Employee = (function() { return Employee; }()); -var employee = new Employee('John Doe'); +const employee = new Employee('John Doe'); console.log('Employee name: ' + employee.getName()); // Employee name: John Doe delete employee.name; console.log('Employee name: ' + employee.getName()); // Employee name: John Doe @@ -1242,12 +1241,12 @@ function renderLargeShapes(shapes) { shape.setHeight(5); } - let area = shape.getArea(); + const area = shape.getArea(); shape.render(area); }) } -let shapes = [new Rectangle(), new Rectangle(), new Square()]; +const shapes = [new Rectangle(), new Rectangle(), new Square()]; renderLargeShapes(shapes); ``` **[⬆ back to top](#table-of-contents)** @@ -1284,7 +1283,7 @@ class DOMTraverser { } } -let $ = new DOMTraverser({ +const $ = new DOMTraverser({ rootNode: document.getElementsByTagName('body'), animationModule: function() {} // Most of the time, we won't need to animate when traversing. // ... @@ -1317,7 +1316,7 @@ class DOMTraverser { } } -let $ = new DOMTraverser({ +const $ = new DOMTraverser({ rootNode: document.getElementsByTagName('body'), options: { animationModule: function() {} @@ -1375,7 +1374,7 @@ class InventoryRequester { } } -let inventoryTracker = new InventoryTracker(['apples', 'bananas']); +const inventoryTracker = new InventoryTracker(['apples', 'bananas']); inventoryTracker.requestItems(); ``` @@ -1416,7 +1415,7 @@ class InventoryRequesterV2 { // By constructing our dependencies externally and injecting them, we can easily // substitute our request module for a fancy new one that uses WebSockets. -let inventoryTracker = new InventoryTracker(['apples', 'bananas'], new InventoryRequesterV2()); +const inventoryTracker = new InventoryTracker(['apples', 'bananas'], new InventoryRequesterV2()); inventoryTracker.requestItems(); ``` **[⬆ back to top](#table-of-contents)** @@ -1429,7 +1428,7 @@ classes until you find yourself needing larger and more complex objects. **Bad:** ```javascript -var Animal = function(age) { +const Animal = function(age) { if (!(this instanceof Animal)) { throw new Error("Instantiate Animal with `new`"); } @@ -1439,7 +1438,7 @@ var Animal = function(age) { Animal.prototype.move = function() {}; -var Mammal = function(age, furColor) { +const Mammal = function(age, furColor) { if (!(this instanceof Mammal)) { throw new Error("Instantiate Mammal with `new`"); } @@ -1452,7 +1451,7 @@ Mammal.prototype = Object.create(Animal.prototype); Mammal.prototype.constructor = Mammal; Mammal.prototype.liveBirth = function() {}; -var Human = function(age, furColor, languageSpoken) { +const Human = function(age, furColor, languageSpoken) { if (!(this instanceof Human)) { throw new Error("Instantiate Human with `new`"); } @@ -1532,7 +1531,7 @@ class Car { } } -let car = new Car(); +const car = new Car(); car.setColor('pink'); car.setMake('Ford'); car.setModel('F-150') @@ -1571,7 +1570,7 @@ class Car { } } -let car = new Car() +const car = new Car() .setColor('pink') .setMake('Ford') .setModel('F-150') @@ -1694,19 +1693,19 @@ const assert = require('assert'); describe('MakeMomentJSGreatAgain', function() { it('handles 30-day months', function() { - let date = new MakeMomentJSGreatAgain('1/1/2015'); + const date = new MakeMomentJSGreatAgain('1/1/2015'); date.addDays(30); date.shouldEqual('1/31/2015'); }); it('handles leap year', function() { - let date = new MakeMomentJSGreatAgain('2/1/2016'); + const date = new MakeMomentJSGreatAgain('2/1/2016'); date.addDays(28); assert.equal('02/29/2016', date); }); it('handles non-leap year', function() { - let date = new MakeMomentJSGreatAgain('2/1/2015'); + const date = new MakeMomentJSGreatAgain('2/1/2015'); date.addDays(28); assert.equal('03/01/2015', date); }); @@ -1780,9 +1779,9 @@ require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Marti ```javascript async function getCleanCodeArticle() { try { - var request = await require('request-promise') - var response = await request.get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin'); - var fileHandle = await require('fs-promise'); + const request = await require('request-promise') + const response = await request.get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin'); + const fileHandle = await require('fs-promise'); await fileHandle.writeFile('article.html', response); console.log('File written'); @@ -1884,11 +1883,11 @@ they want. The point is, no matter what you all choose, just be consistent. **Bad:** ```javascript -var DAYS_IN_WEEK = 7; -var daysInMonth = 30; +const DAYS_IN_WEEK = 7; +const daysInMonth = 30; -var songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; -var Artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; +const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; +const Artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; function eraseDatabase() {} function restore_database() {} @@ -1899,11 +1898,11 @@ class Alpaca {} **Good**: ```javascript -var DAYS_IN_WEEK = 7; -var DAYS_IN_MONTH = 30; +const DAYS_IN_WEEK = 7; +const DAYS_IN_MONTH = 30; -var songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; -var artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; +const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; +const artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; function eraseDatabase() {} function restoreDatabase() {} @@ -1935,7 +1934,7 @@ class PerformanceReview { } getPeerReviews() { - let peers = this.lookupPeers(); + const peers = this.lookupPeers(); // ... } @@ -1946,7 +1945,7 @@ class PerformanceReview { } getManagerReview() { - let manager = this.lookupManager(); + const manager = this.lookupManager(); } getSelfReview() { @@ -1972,7 +1971,7 @@ class PerformanceReview { } getPeerReviews() { - let peers = this.lookupPeers(); + const peers = this.lookupPeers(); // ... } @@ -1981,7 +1980,7 @@ class PerformanceReview { } getManagerReview() { - let manager = this.lookupManager(); + const manager = this.lookupManager(); } lookupMananger() { @@ -2007,15 +2006,15 @@ Comments are an apology, not a requirement. Good code *mostly* documents itself. ```javascript function hashIt(data) { // The hash - var hash = 0; + let hash = 0; // Length of string - var length = data.length; + const length = data.length; // Loop through every character in data - for (var i = 0; i < length; i++) { + for (let i = 0; i < length; i++) { // Get character code. - var char = data.charCodeAt(i); + const char = data.charCodeAt(i); // Make the hash hash = ((hash << 5) - hash) + char; // Convert to 32-bit integer @@ -2028,11 +2027,11 @@ function hashIt(data) { ```javascript function hashIt(data) { - var hash = 0; - var length = data.length; + let hash = 0; + const length = data.length; - for (var i = 0; i < length; i++) { - var char = data.charCodeAt(i); + for (let i = 0; i < length; i++) { + const char = data.charCodeAt(i); hash = ((hash << 5) - hash) + char; // Convert to 32-bit integer @@ -2094,7 +2093,7 @@ proper indentation and formatting give the visual structure to your code. //////////////////////////////////////////////////////////////////////////////// // Scope Model Instantiation //////////////////////////////////////////////////////////////////////////////// -let $scope.model = { +const $scope.model = { menu: 'foo', nav: 'bar' }; @@ -2102,19 +2101,19 @@ let $scope.model = { //////////////////////////////////////////////////////////////////////////////// // Action setup //////////////////////////////////////////////////////////////////////////////// -let actions = function() { +const actions = function() { // ... } ``` **Good**: ```javascript -let $scope.model = { +const $scope.model = { menu: 'foo', nav: 'bar' }; -let actions = function() { +const actions = function() { // ... } ```