From 17b01a2b8c447e608584029a3cd9f029b8038703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Scho=CC=88nwald?= Date: Fri, 6 Jan 2017 22:59:42 +0100 Subject: [PATCH 01/10] Change var and let to const where necessary --- README.md | 223 +++++++++++++++++++++++++++--------------------------- 1 file changed, 111 insertions(+), 112 deletions(-) diff --git a/README.md b/README.md index 17e17fcd..036ce79f 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,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)** @@ -94,16 +94,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(); } ``` @@ -131,7 +131,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(); @@ -145,7 +145,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(); @@ -163,7 +163,7 @@ variable name. **Bad:** ```javascript -var Car = { +const Car = { carMake: 'Honda', carModel: 'Accord', carColor: 'Blue' @@ -176,7 +176,7 @@ function paintCar(car) { **Good**: ```javascript -var Car = { +const Car = { make: 'Honda', model: 'Accord', color: 'Blue' @@ -193,7 +193,7 @@ function paintCar(car) { **Bad:** ```javascript function createMicrobrewery(name) { - var breweryName; + let breweryName; if (name) { breweryName = name; } else { @@ -205,7 +205,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)** @@ -236,7 +236,7 @@ function createMenu(title, body, buttonText, cancellable) { **Good**: ```javascript -var menuConfig = { +const menuConfig = { title: 'Foo', body: 'Bar', buttonText: 'Baz', @@ -262,7 +262,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); } @@ -285,7 +285,7 @@ function emailClientIfNeeded(client) { } function isClientActive(client) { - let clientRecord = database.lookup(client); + const clientRecord = database.lookup(client); return clientRecord.isActive(); } ``` @@ -299,7 +299,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); @@ -311,7 +311,7 @@ function dateAddMonth(date, month) { // ... } -let date = new Date(); +const date = new Date(); dateAddMonth(date, 1); ``` **[⬆ back to top](#table-of-contents)** @@ -324,19 +324,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... }); @@ -350,15 +350,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( // ... ); }) }); @@ -366,20 +366,20 @@ 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... - }) + }) } ``` **[⬆ back to top](#table-of-contents)** @@ -395,10 +395,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 @@ -410,10 +410,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 @@ -428,17 +428,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 @@ -473,7 +472,7 @@ function writeForumComment(subject = 'No subject', body = 'No text') { **Bad:** ```javascript -var menuConfig = { +const menuConfig = { title: null, body: 'Bar', buttonText: null, @@ -493,7 +492,7 @@ createMenu(menuConfig); **Good**: ```javascript -var menuConfig = { +const menuConfig = { title: 'Order', // User did not include 'body' key buttonText: 'Send', @@ -563,7 +562,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(' '); @@ -580,8 +579,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']; @@ -602,14 +601,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); } @@ -627,14 +626,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); } @@ -670,9 +669,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; } ``` @@ -695,7 +694,7 @@ const programmerOutput = [ } ]; -var totalOutput = programmerOutput +const totalOutput = programmerOutput .map((programmer) => programmer.linesOfCode) .reduce((acc, linesOfCode) => acc + linesOfCode, 0); ``` @@ -871,14 +870,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++) { // ... } ``` @@ -899,7 +898,7 @@ function newRequestModule(url) { // ... } -var req = newRequestModule; +const req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); ``` @@ -910,7 +909,7 @@ function newRequestModule(url) { // ... } -var req = newRequestModule; +const req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); ``` **[⬆ back to top](#table-of-contents)** @@ -941,7 +940,7 @@ class BankAccount { } } -let bankAccount = new BankAccount(); +const bankAccount = new BankAccount(); // Buy shoes... bankAccount.balance = bankAccount.balance - 100; @@ -962,7 +961,7 @@ class BankAccount { } } -let bankAccount = new BankAccount(); +const bankAccount = new BankAccount(); // Buy shoes... bankAccount.withdraw(100); @@ -976,7 +975,7 @@ This can be accomplished through closures (for ES5 and below). **Bad:** ```javascript -var Employee = function(name) { +const Employee = function(name) { this.name = name; } @@ -984,7 +983,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 @@ -992,7 +991,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; @@ -1002,7 +1001,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 @@ -1241,12 +1240,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)** @@ -1283,7 +1282,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. // ... @@ -1316,9 +1315,9 @@ class DOMTraverser { } } -let $ = new DOMTraverser({ +const $ = new DOMTraverser({ rootNode: document.getElementsByTagName('body'), - options: { + options: { animationModule: function() {} } }); @@ -1374,7 +1373,7 @@ class InventoryRequester { } } -let inventoryTracker = new InventoryTracker(['apples', 'bananas']); +const inventoryTracker = new InventoryTracker(['apples', 'bananas']); inventoryTracker.requestItems(); ``` @@ -1415,7 +1414,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)** @@ -1428,7 +1427,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`"); } @@ -1438,7 +1437,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`"); } @@ -1451,7 +1450,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`"); } @@ -1531,7 +1530,7 @@ class Car { } } -let car = new Car(); +const car = new Car(); car.setColor('pink'); car.setMake('Ford'); car.setModel('F-150') @@ -1570,7 +1569,7 @@ class Car { } } -let car = new Car() +const car = new Car() .setColor('pink') .setMake('Ford') .setModel('F-150') @@ -1693,19 +1692,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'); + cosnt 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'); + cosnt date = new MakeMomentJSGreatAgain('2/1/2015'); date.addDays(28); assert.equal('03/01/2015', date); }); @@ -1779,9 +1778,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'); @@ -1810,11 +1809,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() {} @@ -1825,11 +1824,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() {} @@ -1861,7 +1860,7 @@ class PerformanceReview { } getPeerReviews() { - let peers = this.lookupPeers(); + const peers = this.lookupPeers(); // ... } @@ -1872,7 +1871,7 @@ class PerformanceReview { } getManagerReview() { - let manager = this.lookupManager(); + const manager = this.lookupManager(); } getSelfReview() { @@ -1898,7 +1897,7 @@ class PerformanceReview { } getPeerReviews() { - let peers = this.lookupPeers(); + const peers = this.lookupPeers(); // ... } @@ -1907,7 +1906,7 @@ class PerformanceReview { } getManagerReview() { - let manager = this.lookupManager(); + const manager = this.lookupManager(); } lookupMananger() { @@ -1933,15 +1932,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 @@ -1954,11 +1953,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 @@ -2020,7 +2019,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' }; @@ -2028,19 +2027,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() { // ... } ``` From 2200e40ad55fc6160c5a8e2ea025c7b87c973bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Scho=CC=88nwald?= Date: Sat, 7 Jan 2017 15:06:29 +0100 Subject: [PATCH 02/10] Fix typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 036ce79f..7616bd7c 100644 --- a/README.md +++ b/README.md @@ -1698,13 +1698,13 @@ describe('MakeMomentJSGreatAgain', function() { }); it('handles leap year', function() { - cosnt 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() { - cosnt date = new MakeMomentJSGreatAgain('2/1/2015'); + const date = new MakeMomentJSGreatAgain('2/1/2015'); date.addDays(28); assert.equal('03/01/2015', date); }); From a1af85bccc62109826a95fecd6e362e70e484dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Scho=CC=88nwald?= Date: Sat, 7 Jan 2017 15:26:22 +0100 Subject: [PATCH 03/10] Edit paragraph es6-const --- README.md | 317 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 198 insertions(+), 119 deletions(-) diff --git a/README.md b/README.md index 7616bd7c..c4427593 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,9 @@ 5. [Classes](#classes) 6. [Testing](#testing) 7. [Concurrency](#concurrency) - 8. [Formatting](#formatting) - 9. [Comments](#comments) + 8. [Error Handling](#error-handling) + 9. [Formatting](#formatting) + 10. [Comments](#comments) ## Introduction ![Humorous image of software quality estimation as a count of how many expletives @@ -43,20 +44,19 @@ improvement. Beat up the code instead! **Bad:** ```javascript -const yyyymmdstr = moment().format('YYYY/MM/DD'); +var yyyymmdstr = moment().format('YYYY/MM/DD'); ``` **Good**: ```javascript -const yearMonthDay = moment().format('YYYY/MM/DD'); +var yearMonthDay = moment().format('YYYY/MM/DD'); ``` **[⬆ back to top](#table-of-contents)** -### Use ES6 constants when variable values do not change -In the bad example, the variable can be changed. -When you declare a constant, the variable should stay -the same throughout the program. - +### Use ES6 constants when variable will not be reassigned +In the bad example, the variable can be reassigned. +When you declare a constant, the variable can only be altered. +If you want to reassign a variable use `let`. **Bad:** ```javascript @@ -66,6 +66,11 @@ var FIRST_US_PRESIDENT = "George Washington"; **Good**: ```javascript const FIRST_US_PRESIDENT = "George Washington"; + +let CURRENT_US_PRESIDENT = "Donald Trump"; +if (bool) { + CURRENT_US_PRESIDENT = "somone else"; +} ``` **[⬆ back to top](#table-of-contents)** @@ -94,16 +99,16 @@ Make your names searchable. **Bad:** ```javascript // What the heck is 525600 for? -for (let i = 0; i < 525600; i++) { +for (var i = 0; i < 525600; i++) { runCronJob(); } ``` **Good**: ```javascript -// Declare them as capitalized `const` globals. -const MINUTES_IN_A_YEAR = 525600; -for (let i = 0; i < MINUTES_IN_A_YEAR; i++) { +// Declare them as capitalized `var` globals. +var MINUTES_IN_A_YEAR = 525600; +for (var i = 0; i < MINUTES_IN_A_YEAR; i++) { runCronJob(); } ``` @@ -131,7 +136,7 @@ Explicit is better than implicit. **Bad:** ```javascript -const locations = ['Austin', 'New York', 'San Francisco']; +var locations = ['Austin', 'New York', 'San Francisco']; locations.forEach((l) => { doStuff(); doSomeOtherStuff(); @@ -145,7 +150,7 @@ locations.forEach((l) => { **Good**: ```javascript -const locations = ['Austin', 'New York', 'San Francisco']; +var locations = ['Austin', 'New York', 'San Francisco']; locations.forEach((location) => { doStuff(); doSomeOtherStuff(); @@ -163,7 +168,7 @@ variable name. **Bad:** ```javascript -const Car = { +var Car = { carMake: 'Honda', carModel: 'Accord', carColor: 'Blue' @@ -176,7 +181,7 @@ function paintCar(car) { **Good**: ```javascript -const Car = { +var Car = { make: 'Honda', model: 'Accord', color: 'Blue' @@ -193,7 +198,7 @@ function paintCar(car) { **Bad:** ```javascript function createMicrobrewery(name) { - let breweryName; + var breweryName; if (name) { breweryName = name; } else { @@ -205,7 +210,7 @@ function createMicrobrewery(name) { **Good**: ```javascript function createMicrobrewery(name) { - const breweryName = name || 'Hipster Brew Co.' + var breweryName = name || 'Hipster Brew Co.' } ``` **[⬆ back to top](#table-of-contents)** @@ -236,7 +241,7 @@ function createMenu(title, body, buttonText, cancellable) { **Good**: ```javascript -const menuConfig = { +var menuConfig = { title: 'Foo', body: 'Bar', buttonText: 'Baz', @@ -262,7 +267,7 @@ this guide other than this, you'll be ahead of many developers. ```javascript function emailClients(clients) { clients.forEach(client => { - const clientRecord = database.lookup(client); + let clientRecord = database.lookup(client); if (clientRecord.isActive()) { email(client); } @@ -285,7 +290,7 @@ function emailClientIfNeeded(client) { } function isClientActive(client) { - const clientRecord = database.lookup(client); + let clientRecord = database.lookup(client); return clientRecord.isActive(); } ``` @@ -299,7 +304,7 @@ function dateAdd(date, month) { // ... } -const date = new Date(); +let date = new Date(); // It's hard to to tell from the function name what is added dateAdd(date, 1); @@ -311,7 +316,7 @@ function dateAddMonth(date, month) { // ... } -const date = new Date(); +let date = new Date(); dateAddMonth(date, 1); ``` **[⬆ back to top](#table-of-contents)** @@ -324,19 +329,19 @@ testing. **Bad:** ```javascript function parseBetterJSAlternative(code) { - const REGEXES = [ + let REGEXES = [ // ... ]; - const statements = code.split(' '); - const tokens = []; + let statements = code.split(' '); + let tokens; REGEXES.forEach((REGEX) => { statements.forEach((statement) => { // ... }) }); - const ast = []; + let ast; tokens.forEach((token) => { // lex... }); @@ -350,15 +355,15 @@ function parseBetterJSAlternative(code) { **Good**: ```javascript function tokenize(code) { - const REGEXES = [ + let REGEXES = [ // ... ]; - const statements = code.split(' '); - const tokens = []; + let statements = code.split(' '); + let tokens; REGEXES.forEach((REGEX) => { statements.forEach((statement) => { - tokens.push( // ... ); + // ... }) }); @@ -366,17 +371,17 @@ function tokenize(code) { } function lexer(tokens) { - const ast = []; + let ast; tokens.forEach((token) => { - ast.push( // ... ); + // lex... }); return ast; } function parseBetterJSAlternative(code) { - const tokens = tokenize(code); - const ast = lexer(tokens); + let tokens = tokenize(code); + let ast = lexer(tokens); ast.forEach((node) => { // parse... }) @@ -395,10 +400,10 @@ generic functions quite easy. Take advantage of that! ```javascript function showDeveloperList(developers) { developers.forEach(developers => { - const expectedSalary = developer.calculateExpectedSalary(); - const experience = developer.getExperience(); - const githubLink = developer.getGithubLink(); - const data = { + var expectedSalary = developer.calculateExpectedSalary(); + var experience = developer.getExperience(); + var githubLink = developer.getGithubLink(); + var data = { expectedSalary: expectedSalary, experience: experience, githubLink: githubLink @@ -410,10 +415,10 @@ function showDeveloperList(developers) { function showManagerList(managers) { managers.forEach(manager => { - const expectedSalary = manager.calculateExpectedSalary(); - const experience = manager.getExperience(); - const portfolio = manager.getMBAProjects(); - const data = { + var expectedSalary = manager.calculateExpectedSalary(); + var experience = manager.getExperience(); + var portfolio = manager.getMBAProjects(); + var data = { expectedSalary: expectedSalary, experience: experience, portfolio: portfolio @@ -428,16 +433,17 @@ function showManagerList(managers) { ```javascript function showList(employees) { employees.forEach(employee => { - const expectedSalary = employee.calculateExpectedSalary(); - const experience = employee.getExperience(); - - let portfolio = employee.getGithubLink(); + var expectedSalary = employee.calculateExpectedSalary(); + var experience = employee.getExperience(); + var portfolio; if (employee.type === 'manager') { portfolio = employee.getMBAProjects(); + } else { + portfolio = employee.getGithubLink(); } - const data = { + var data = { expectedSalary: expectedSalary, experience: experience, portfolio: portfolio @@ -472,7 +478,7 @@ function writeForumComment(subject = 'No subject', body = 'No text') { **Bad:** ```javascript -const menuConfig = { +var menuConfig = { title: null, body: 'Bar', buttonText: null, @@ -492,7 +498,7 @@ createMenu(menuConfig); **Good**: ```javascript -const menuConfig = { +var menuConfig = { title: 'Order', // User did not include 'body' key buttonText: 'Send', @@ -507,7 +513,7 @@ function createMenu(config) { cancellable: true }, config); - // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} + // config now equals: {title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true} // ... } @@ -562,7 +568,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. -let name = 'Ryan McDermott'; +var name = 'Ryan McDermott'; function splitIntoFirstAndLastName() { name = name.split(' '); @@ -579,8 +585,8 @@ function splitIntoFirstAndLastName(name) { return name.split(' '); } -const name = 'Ryan McDermott' -const newName = splitIntoFirstAndLastName(name); +var name = 'Ryan McDermott' +var newName = splitIntoFirstAndLastName(name); console.log(name); // 'Ryan McDermott'; console.log(newName); // ['Ryan', 'McDermott']; @@ -601,14 +607,14 @@ would be much better to just use ES6 classes and simply extend the `Array` globa **Bad:** ```javascript Array.prototype.diff = function(comparisonArray) { - const values = []; - const hash = {}; + var values = []; + var hash = {}; - for (let i of comparisonArray) { + for (var i of comparisonArray) { hash[i] = true; } - for (let i of this) { + for (var i of this) { if (!hash[i]) { values.push(i); } @@ -626,14 +632,14 @@ class SuperArray extends Array { } diff(comparisonArray) { - const values = []; - const hash = {}; + var values = []; + var hash = {}; - for (let i of comparisonArray) { + for (var i of comparisonArray) { hash[i] = true; } - for (let i of this) { + for (var i of this) { if (!hash[i]) { values.push(i); } @@ -669,9 +675,9 @@ const programmerOutput = [ } ]; -let totalOutput = 0; +var totalOutput = 0; -for (let i = 0; i < programmerOutput.length; i++) { +for (var i = 0; i < programmerOutput.length; i++) { totalOutput += programmerOutput[i].linesOfCode; } ``` @@ -694,7 +700,7 @@ const programmerOutput = [ } ]; -const totalOutput = programmerOutput +var totalOutput = programmerOutput .map((programmer) => programmer.linesOfCode) .reduce((acc, linesOfCode) => acc + linesOfCode, 0); ``` @@ -766,7 +772,7 @@ class Airplane { return getMaxAltitude() - getPassengerCount(); case 'Air Force One': return getMaxAltitude(); - case 'Cesna': + case 'Cessna': return getMaxAltitude() - getFuelExpenditure(); } } @@ -793,7 +799,7 @@ class AirForceOne extends Airplane { } } -class Cesna extends Airplane { +class Cessna extends Airplane { //... getCruisingAltitude() { return getMaxAltitude() - getFuelExpenditure(); @@ -870,14 +876,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 (let i = 0, len = list.length; i < len; i++) { +for (var i = 0, len = list.length; i < len; i++) { // ... } ``` **Good**: ```javascript -for (let i = 0; i < list.length; i++) { +for (var i = 0; i < list.length; i++) { // ... } ``` @@ -898,7 +904,7 @@ function newRequestModule(url) { // ... } -const req = newRequestModule; +var req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); ``` @@ -909,7 +915,7 @@ function newRequestModule(url) { // ... } -const req = newRequestModule; +var req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); ``` **[⬆ back to top](#table-of-contents)** @@ -940,7 +946,7 @@ class BankAccount { } } -const bankAccount = new BankAccount(); +let bankAccount = new BankAccount(); // Buy shoes... bankAccount.balance = bankAccount.balance - 100; @@ -961,7 +967,7 @@ class BankAccount { } } -const bankAccount = new BankAccount(); +let bankAccount = new BankAccount(); // Buy shoes... bankAccount.withdraw(100); @@ -975,7 +981,7 @@ This can be accomplished through closures (for ES5 and below). **Bad:** ```javascript -const Employee = function(name) { +var Employee = function(name) { this.name = name; } @@ -983,7 +989,7 @@ Employee.prototype.getName = function() { return this.name; } -const employee = new Employee('John Doe'); +var 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 @@ -991,7 +997,7 @@ console.log('Employee name: ' + employee.getName()); // Employee name: undefined **Good**: ```javascript -const Employee = (function() { +var Employee = (function() { function Employee(name) { this.getName = function() { return name; @@ -1001,7 +1007,7 @@ const Employee = (function() { return Employee; }()); -const employee = new Employee('John Doe'); +var 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 @@ -1240,12 +1246,12 @@ function renderLargeShapes(shapes) { shape.setHeight(5); } - const area = shape.getArea(); + let area = shape.getArea(); shape.render(area); }) } -const shapes = [new Rectangle(), new Rectangle(), new Square()]; +let shapes = [new Rectangle(), new Rectangle(), new Square()]; renderLargeShapes(shapes); ``` **[⬆ back to top](#table-of-contents)** @@ -1282,7 +1288,7 @@ class DOMTraverser { } } -const $ = new DOMTraverser({ +let $ = new DOMTraverser({ rootNode: document.getElementsByTagName('body'), animationModule: function() {} // Most of the time, we won't need to animate when traversing. // ... @@ -1315,7 +1321,7 @@ class DOMTraverser { } } -const $ = new DOMTraverser({ +let $ = new DOMTraverser({ rootNode: document.getElementsByTagName('body'), options: { animationModule: function() {} @@ -1373,7 +1379,7 @@ class InventoryRequester { } } -const inventoryTracker = new InventoryTracker(['apples', 'bananas']); +let inventoryTracker = new InventoryTracker(['apples', 'bananas']); inventoryTracker.requestItems(); ``` @@ -1414,7 +1420,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. -const inventoryTracker = new InventoryTracker(['apples', 'bananas'], new InventoryRequesterV2()); +let inventoryTracker = new InventoryTracker(['apples', 'bananas'], new InventoryRequesterV2()); inventoryTracker.requestItems(); ``` **[⬆ back to top](#table-of-contents)** @@ -1427,7 +1433,7 @@ classes until you find yourself needing larger and more complex objects. **Bad:** ```javascript -const Animal = function(age) { +var Animal = function(age) { if (!(this instanceof Animal)) { throw new Error("Instantiate Animal with `new`"); } @@ -1437,7 +1443,7 @@ const Animal = function(age) { Animal.prototype.move = function() {}; -const Mammal = function(age, furColor) { +var Mammal = function(age, furColor) { if (!(this instanceof Mammal)) { throw new Error("Instantiate Mammal with `new`"); } @@ -1450,7 +1456,7 @@ Mammal.prototype = Object.create(Animal.prototype); Mammal.prototype.constructor = Mammal; Mammal.prototype.liveBirth = function() {}; -const Human = function(age, furColor, languageSpoken) { +var Human = function(age, furColor, languageSpoken) { if (!(this instanceof Human)) { throw new Error("Instantiate Human with `new`"); } @@ -1530,7 +1536,7 @@ class Car { } } -const car = new Car(); +let car = new Car(); car.setColor('pink'); car.setMake('Ford'); car.setModel('F-150') @@ -1569,7 +1575,7 @@ class Car { } } -const car = new Car() +let car = new Car() .setColor('pink') .setMake('Ford') .setModel('F-150') @@ -1692,19 +1698,19 @@ const assert = require('assert'); describe('MakeMomentJSGreatAgain', function() { it('handles 30-day months', function() { - const date = new MakeMomentJSGreatAgain('1/1/2015'); + let date = new MakeMomentJSGreatAgain('1/1/2015'); date.addDays(30); date.shouldEqual('1/31/2015'); }); it('handles leap year', function() { - const date = new MakeMomentJSGreatAgain('2/1/2016'); + let date = new MakeMomentJSGreatAgain('2/1/2016'); date.addDays(28); assert.equal('02/29/2016', date); }); it('handles non-leap year', function() { - const date = new MakeMomentJSGreatAgain('2/1/2015'); + let date = new MakeMomentJSGreatAgain('2/1/2015'); date.addDays(28); assert.equal('03/01/2015', date); }); @@ -1778,9 +1784,9 @@ require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Marti ```javascript async function getCleanCodeArticle() { try { - 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'); + 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'); await fileHandle.writeFile('article.html', response); console.log('File written'); @@ -1792,6 +1798,79 @@ async function getCleanCodeArticle() { **[⬆ back to top](#table-of-contents)** +## **Error Handling** +Thrown errors are a good thing! They mean the runtime has successfully +identified when something in your program has gone wrong and it's letting +you know by stopping function execution on the current stack, killing the +process (in Node), and notifying you in the console with a stack trace. + +### Don't ignore caught errors +Doing nothing with a caught error doesn't give you the ability to ever fix +or react to said error. Logging the error to the console (`console.log`) +isn't much better as often times it can get lost in a sea of things printed +to the console. If you wrap any bit of code in a `try/catch` it means you +think an error may occur there and therefore you should have a plan, +or create a code path, for when it occurs. + +**Bad:** +```javascript +try { + functionThatMightThrow(); +} catch (error) { + console.log(error); +} +``` + +**Good:** +```javascript +try { + functionThatMightThrow(); +} catch (error) { + // One option (more noisy than console.log): + console.error(error); + // Another option: + notifyUserOfError(error); + // Another option: + reportErrorToService(error); + // OR do all three! +} +``` + +### Don't ignore rejected promises +For the same reason you shouldn't ignore caught errors +from `try/catch`. + +**Bad:** +```javascript +getdata() +.then(data => { + functionThatMightThrow(data); +}) +.catch(error => { + console.log(error); +}); +``` + +**Good:** +```javascript +getdata() +.then(data => { + functionThatMightThrow(data); +}) +.catch(error => { + // One option (more noisy than console.log): + console.error(error); + // Another option: + notifyUserOfError(error); + // Another option: + reportErrorToService(error); + // OR do all three! +}); +``` + +**[⬆ back to top](#table-of-contents)** + + ## **Formatting** Formatting is subjective. Like many rules herein, there is no hard and fast rule that you must follow. The main point is DO NOT ARGUE over formatting. @@ -1809,11 +1888,11 @@ they want. The point is, no matter what you all choose, just be consistent. **Bad:** ```javascript -const DAYS_IN_WEEK = 7; -const daysInMonth = 30; +var DAYS_IN_WEEK = 7; +var daysInMonth = 30; -const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; -const Artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; +var songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; +var Artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; function eraseDatabase() {} function restore_database() {} @@ -1824,11 +1903,11 @@ class Alpaca {} **Good**: ```javascript -const DAYS_IN_WEEK = 7; -const DAYS_IN_MONTH = 30; +var DAYS_IN_WEEK = 7; +var DAYS_IN_MONTH = 30; -const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; -const artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; +var songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; +var artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; function eraseDatabase() {} function restoreDatabase() {} @@ -1860,7 +1939,7 @@ class PerformanceReview { } getPeerReviews() { - const peers = this.lookupPeers(); + let peers = this.lookupPeers(); // ... } @@ -1871,7 +1950,7 @@ class PerformanceReview { } getManagerReview() { - const manager = this.lookupManager(); + let manager = this.lookupManager(); } getSelfReview() { @@ -1897,7 +1976,7 @@ class PerformanceReview { } getPeerReviews() { - const peers = this.lookupPeers(); + let peers = this.lookupPeers(); // ... } @@ -1906,7 +1985,7 @@ class PerformanceReview { } getManagerReview() { - const manager = this.lookupManager(); + let manager = this.lookupManager(); } lookupMananger() { @@ -1932,15 +2011,15 @@ Comments are an apology, not a requirement. Good code *mostly* documents itself. ```javascript function hashIt(data) { // The hash - let hash = 0; + var hash = 0; // Length of string - const length = data.length; + var length = data.length; // Loop through every character in data - for (let i = 0; i < length; i++) { + for (var i = 0; i < length; i++) { // Get character code. - const char = data.charCodeAt(i); + var char = data.charCodeAt(i); // Make the hash hash = ((hash << 5) - hash) + char; // Convert to 32-bit integer @@ -1953,11 +2032,11 @@ function hashIt(data) { ```javascript function hashIt(data) { - let hash = 0; - const length = data.length; + var hash = 0; + var length = data.length; - for (let i = 0; i < length; i++) { - const char = data.charCodeAt(i); + for (var i = 0; i < length; i++) { + var char = data.charCodeAt(i); hash = ((hash << 5) - hash) + char; // Convert to 32-bit integer @@ -2019,7 +2098,7 @@ proper indentation and formatting give the visual structure to your code. //////////////////////////////////////////////////////////////////////////////// // Scope Model Instantiation //////////////////////////////////////////////////////////////////////////////// -const $scope.model = { +let $scope.model = { menu: 'foo', nav: 'bar' }; @@ -2027,19 +2106,19 @@ const $scope.model = { //////////////////////////////////////////////////////////////////////////////// // Action setup //////////////////////////////////////////////////////////////////////////////// -const actions = function() { +let actions = function() { // ... } ``` **Good**: ```javascript -const $scope.model = { +let $scope.model = { menu: 'foo', nav: 'bar' }; -const actions = function() { +let actions = function() { // ... } ``` From 2a3af4c5666108276d083f4f49897746a73d50d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Scho=CC=88nwald?= Date: Sat, 7 Jan 2017 15:30:59 +0100 Subject: [PATCH 04/10] Revert "Edit paragraph es6-const" This reverts commit a1af85bccc62109826a95fecd6e362e70e484dea. --- README.md | 317 ++++++++++++++++++++---------------------------------- 1 file changed, 119 insertions(+), 198 deletions(-) diff --git a/README.md b/README.md index c4427593..7616bd7c 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,8 @@ 5. [Classes](#classes) 6. [Testing](#testing) 7. [Concurrency](#concurrency) - 8. [Error Handling](#error-handling) - 9. [Formatting](#formatting) - 10. [Comments](#comments) + 8. [Formatting](#formatting) + 9. [Comments](#comments) ## Introduction ![Humorous image of software quality estimation as a count of how many expletives @@ -44,19 +43,20 @@ 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)** -### Use ES6 constants when variable will not be reassigned -In the bad example, the variable can be reassigned. -When you declare a constant, the variable can only be altered. -If you want to reassign a variable use `let`. +### Use ES6 constants when variable values do not change +In the bad example, the variable can be changed. +When you declare a constant, the variable should stay +the same throughout the program. + **Bad:** ```javascript @@ -66,11 +66,6 @@ var FIRST_US_PRESIDENT = "George Washington"; **Good**: ```javascript const FIRST_US_PRESIDENT = "George Washington"; - -let CURRENT_US_PRESIDENT = "Donald Trump"; -if (bool) { - CURRENT_US_PRESIDENT = "somone else"; -} ``` **[⬆ back to top](#table-of-contents)** @@ -99,16 +94,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(); } ``` @@ -136,7 +131,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(); @@ -150,7 +145,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(); @@ -168,7 +163,7 @@ variable name. **Bad:** ```javascript -var Car = { +const Car = { carMake: 'Honda', carModel: 'Accord', carColor: 'Blue' @@ -181,7 +176,7 @@ function paintCar(car) { **Good**: ```javascript -var Car = { +const Car = { make: 'Honda', model: 'Accord', color: 'Blue' @@ -198,7 +193,7 @@ function paintCar(car) { **Bad:** ```javascript function createMicrobrewery(name) { - var breweryName; + let breweryName; if (name) { breweryName = name; } else { @@ -210,7 +205,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)** @@ -241,7 +236,7 @@ function createMenu(title, body, buttonText, cancellable) { **Good**: ```javascript -var menuConfig = { +const menuConfig = { title: 'Foo', body: 'Bar', buttonText: 'Baz', @@ -267,7 +262,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); } @@ -290,7 +285,7 @@ function emailClientIfNeeded(client) { } function isClientActive(client) { - let clientRecord = database.lookup(client); + const clientRecord = database.lookup(client); return clientRecord.isActive(); } ``` @@ -304,7 +299,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); @@ -316,7 +311,7 @@ function dateAddMonth(date, month) { // ... } -let date = new Date(); +const date = new Date(); dateAddMonth(date, 1); ``` **[⬆ back to top](#table-of-contents)** @@ -329,19 +324,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... }); @@ -355,15 +350,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( // ... ); }) }); @@ -371,17 +366,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... }) @@ -400,10 +395,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 @@ -415,10 +410,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 @@ -433,17 +428,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 @@ -478,7 +472,7 @@ function writeForumComment(subject = 'No subject', body = 'No text') { **Bad:** ```javascript -var menuConfig = { +const menuConfig = { title: null, body: 'Bar', buttonText: null, @@ -498,7 +492,7 @@ createMenu(menuConfig); **Good**: ```javascript -var menuConfig = { +const menuConfig = { title: 'Order', // User did not include 'body' key buttonText: 'Send', @@ -513,7 +507,7 @@ function createMenu(config) { cancellable: true }, config); - // config now equals: {title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true} + // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} // ... } @@ -568,7 +562,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(' '); @@ -585,8 +579,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']; @@ -607,14 +601,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); } @@ -632,14 +626,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); } @@ -675,9 +669,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; } ``` @@ -700,7 +694,7 @@ const programmerOutput = [ } ]; -var totalOutput = programmerOutput +const totalOutput = programmerOutput .map((programmer) => programmer.linesOfCode) .reduce((acc, linesOfCode) => acc + linesOfCode, 0); ``` @@ -772,7 +766,7 @@ class Airplane { return getMaxAltitude() - getPassengerCount(); case 'Air Force One': return getMaxAltitude(); - case 'Cessna': + case 'Cesna': return getMaxAltitude() - getFuelExpenditure(); } } @@ -799,7 +793,7 @@ class AirForceOne extends Airplane { } } -class Cessna extends Airplane { +class Cesna extends Airplane { //... getCruisingAltitude() { return getMaxAltitude() - getFuelExpenditure(); @@ -876,14 +870,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++) { // ... } ``` @@ -904,7 +898,7 @@ function newRequestModule(url) { // ... } -var req = newRequestModule; +const req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); ``` @@ -915,7 +909,7 @@ function newRequestModule(url) { // ... } -var req = newRequestModule; +const req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); ``` **[⬆ back to top](#table-of-contents)** @@ -946,7 +940,7 @@ class BankAccount { } } -let bankAccount = new BankAccount(); +const bankAccount = new BankAccount(); // Buy shoes... bankAccount.balance = bankAccount.balance - 100; @@ -967,7 +961,7 @@ class BankAccount { } } -let bankAccount = new BankAccount(); +const bankAccount = new BankAccount(); // Buy shoes... bankAccount.withdraw(100); @@ -981,7 +975,7 @@ This can be accomplished through closures (for ES5 and below). **Bad:** ```javascript -var Employee = function(name) { +const Employee = function(name) { this.name = name; } @@ -989,7 +983,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 @@ -997,7 +991,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; @@ -1007,7 +1001,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 @@ -1246,12 +1240,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)** @@ -1288,7 +1282,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. // ... @@ -1321,7 +1315,7 @@ class DOMTraverser { } } -let $ = new DOMTraverser({ +const $ = new DOMTraverser({ rootNode: document.getElementsByTagName('body'), options: { animationModule: function() {} @@ -1379,7 +1373,7 @@ class InventoryRequester { } } -let inventoryTracker = new InventoryTracker(['apples', 'bananas']); +const inventoryTracker = new InventoryTracker(['apples', 'bananas']); inventoryTracker.requestItems(); ``` @@ -1420,7 +1414,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)** @@ -1433,7 +1427,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`"); } @@ -1443,7 +1437,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`"); } @@ -1456,7 +1450,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`"); } @@ -1536,7 +1530,7 @@ class Car { } } -let car = new Car(); +const car = new Car(); car.setColor('pink'); car.setMake('Ford'); car.setModel('F-150') @@ -1575,7 +1569,7 @@ class Car { } } -let car = new Car() +const car = new Car() .setColor('pink') .setMake('Ford') .setModel('F-150') @@ -1698,19 +1692,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); }); @@ -1784,9 +1778,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'); @@ -1798,79 +1792,6 @@ async function getCleanCodeArticle() { **[⬆ back to top](#table-of-contents)** -## **Error Handling** -Thrown errors are a good thing! They mean the runtime has successfully -identified when something in your program has gone wrong and it's letting -you know by stopping function execution on the current stack, killing the -process (in Node), and notifying you in the console with a stack trace. - -### Don't ignore caught errors -Doing nothing with a caught error doesn't give you the ability to ever fix -or react to said error. Logging the error to the console (`console.log`) -isn't much better as often times it can get lost in a sea of things printed -to the console. If you wrap any bit of code in a `try/catch` it means you -think an error may occur there and therefore you should have a plan, -or create a code path, for when it occurs. - -**Bad:** -```javascript -try { - functionThatMightThrow(); -} catch (error) { - console.log(error); -} -``` - -**Good:** -```javascript -try { - functionThatMightThrow(); -} catch (error) { - // One option (more noisy than console.log): - console.error(error); - // Another option: - notifyUserOfError(error); - // Another option: - reportErrorToService(error); - // OR do all three! -} -``` - -### Don't ignore rejected promises -For the same reason you shouldn't ignore caught errors -from `try/catch`. - -**Bad:** -```javascript -getdata() -.then(data => { - functionThatMightThrow(data); -}) -.catch(error => { - console.log(error); -}); -``` - -**Good:** -```javascript -getdata() -.then(data => { - functionThatMightThrow(data); -}) -.catch(error => { - // One option (more noisy than console.log): - console.error(error); - // Another option: - notifyUserOfError(error); - // Another option: - reportErrorToService(error); - // OR do all three! -}); -``` - -**[⬆ back to top](#table-of-contents)** - - ## **Formatting** Formatting is subjective. Like many rules herein, there is no hard and fast rule that you must follow. The main point is DO NOT ARGUE over formatting. @@ -1888,11 +1809,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() {} @@ -1903,11 +1824,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() {} @@ -1939,7 +1860,7 @@ class PerformanceReview { } getPeerReviews() { - let peers = this.lookupPeers(); + const peers = this.lookupPeers(); // ... } @@ -1950,7 +1871,7 @@ class PerformanceReview { } getManagerReview() { - let manager = this.lookupManager(); + const manager = this.lookupManager(); } getSelfReview() { @@ -1976,7 +1897,7 @@ class PerformanceReview { } getPeerReviews() { - let peers = this.lookupPeers(); + const peers = this.lookupPeers(); // ... } @@ -1985,7 +1906,7 @@ class PerformanceReview { } getManagerReview() { - let manager = this.lookupManager(); + const manager = this.lookupManager(); } lookupMananger() { @@ -2011,15 +1932,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 @@ -2032,11 +1953,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 @@ -2098,7 +2019,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' }; @@ -2106,19 +2027,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() { // ... } ``` From f2888931083d7f9b0728249baae0efdca457cdc2 Mon Sep 17 00:00:00 2001 From: Stewart Rand Date: Fri, 6 Jan 2017 14:34:14 -0400 Subject: [PATCH 05/10] Correct spelling of Cessna airplane --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7616bd7c..77d73dc2 100644 --- a/README.md +++ b/README.md @@ -766,7 +766,7 @@ class Airplane { return getMaxAltitude() - getPassengerCount(); case 'Air Force One': return getMaxAltitude(); - case 'Cesna': + case 'Cessna': return getMaxAltitude() - getFuelExpenditure(); } } @@ -793,7 +793,7 @@ class AirForceOne extends Airplane { } } -class Cesna extends Airplane { +class Cessna extends Airplane { //... getCruisingAltitude() { return getMaxAltitude() - getFuelExpenditure(); From 4d97329b25a5b3b0e995730e9ec680b611eaf866 Mon Sep 17 00:00:00 2001 From: Acidio Alan Date: Fri, 6 Jan 2017 11:45:17 -0200 Subject: [PATCH 06/10] Adjusted the commentthat show the result --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 77d73dc2..d5e6d500 100644 --- a/README.md +++ b/README.md @@ -507,7 +507,7 @@ function createMenu(config) { cancellable: true }, config); - // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} + // config now equals: {title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true} // ... } From ebf2556bc4d35e898828889568c4119f46f10907 Mon Sep 17 00:00:00 2001 From: Jordalgo Date: Fri, 6 Jan 2017 11:41:13 -0500 Subject: [PATCH 07/10] Add: Error Handling Section --- README.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d5e6d500..db58b0d6 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,9 @@ 5. [Classes](#classes) 6. [Testing](#testing) 7. [Concurrency](#concurrency) - 8. [Formatting](#formatting) - 9. [Comments](#comments) + 8. [Error Handling](#error-handling) + 9. [Formatting](#formatting) + 10. [Comments](#comments) ## Introduction ![Humorous image of software quality estimation as a count of how many expletives @@ -1792,6 +1793,79 @@ async function getCleanCodeArticle() { **[⬆ back to top](#table-of-contents)** +## **Error Handling** +Thrown errors are a good thing! They mean the runtime has successfully +identified when something in your program has gone wrong and it's letting +you know by stopping function execution on the current stack, killing the +process (in Node), and notifying you in the console with a stack trace. + +### Don't ignore caught errors +Doing nothing with a caught error doesn't give you the ability to ever fix +or react to said error. Logging the error to the console (`console.log`) +isn't much better as often times it can get lost in a sea of things printed +to the console. If you wrap any bit of code in a `try/catch` it means you +think an error may occur there and therefore you should have a plan, +or create a code path, for when it occurs. + +**Bad:** +```javascript +try { + functionThatMightThrow(); +} catch (error) { + console.log(error); +} +``` + +**Good:** +```javascript +try { + functionThatMightThrow(); +} catch (error) { + // One option (more noisy than console.log): + console.error(error); + // Another option: + notifyUserOfError(error); + // Another option: + reportErrorToService(error); + // OR do all three! +} +``` + +### Don't ignore rejected promises +For the same reason you shouldn't ignore caught errors +from `try/catch`. + +**Bad:** +```javascript +getdata() +.then(data => { + functionThatMightThrow(data); +}) +.catch(error => { + console.log(error); +}); +``` + +**Good:** +```javascript +getdata() +.then(data => { + functionThatMightThrow(data); +}) +.catch(error => { + // One option (more noisy than console.log): + console.error(error); + // Another option: + notifyUserOfError(error); + // Another option: + reportErrorToService(error); + // OR do all three! +}); +``` + +**[⬆ back to top](#table-of-contents)** + + ## **Formatting** Formatting is subjective. Like many rules herein, there is no hard and fast rule that you must follow. The main point is DO NOT ARGUE over formatting. From a4a38e52e6a07e5a19ab3774bede25df9ffd4852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Scho=CC=88nwald?= Date: Sat, 7 Jan 2017 15:32:35 +0100 Subject: [PATCH 08/10] Edit paragraph es6-const again --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index db58b0d6..cf67bd4d 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,10 @@ const yearMonthDay = moment().format('YYYY/MM/DD'); ``` **[⬆ back to top](#table-of-contents)** -### Use ES6 constants when variable values do not change -In the bad example, the variable can be changed. -When you declare a constant, the variable should stay -the same throughout the program. - +### Use ES6 constants when variable will not be reassigned +In the bad example, the variable can be reassigned. +When you declare a constant, the variable can only be altered. +If you want to reassign a variable use `let`. **Bad:** ```javascript @@ -67,6 +66,11 @@ var FIRST_US_PRESIDENT = "George Washington"; **Good**: ```javascript const FIRST_US_PRESIDENT = "George Washington"; + +let CURRENT_US_PRESIDENT = "Donald Trump"; +if (bool) { + CURRENT_US_PRESIDENT = "somone else"; +} ``` **[⬆ back to top](#table-of-contents)** From 3aba718f32f9fe8d3a5fa83c6a108f6d905e6826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Scho=CC=88nwald?= Date: Sat, 7 Jan 2017 15:35:27 +0100 Subject: [PATCH 09/10] Fix merge --- README.md | 233 +++++++++++++++++++++++++++--------------------------- 1 file changed, 115 insertions(+), 118 deletions(-) diff --git a/README.md b/README.md index cf67bd4d..94e7fa2c 100644 --- a/README.md +++ b/README.md @@ -44,19 +44,20 @@ improvement. Beat up the code instead! **Bad:** ```javascript -const yyyymmdstr = moment().format('YYYY/MM/DD'); +var yyyymmdstr = moment().format('YYYY/MM/DD'); ``` **Good**: ```javascript -const yearMonthDay = moment().format('YYYY/MM/DD'); +var yearMonthDay = moment().format('YYYY/MM/DD'); ``` **[⬆ back to top](#table-of-contents)** -### Use ES6 constants when variable will not be reassigned -In the bad example, the variable can be reassigned. -When you declare a constant, the variable can only be altered. -If you want to reassign a variable use `let`. +### Use ES6 constants when variable values do not change +In the bad example, the variable can be changed. +When you declare a constant, the variable should stay +the same throughout the program. + **Bad:** ```javascript @@ -66,11 +67,6 @@ var FIRST_US_PRESIDENT = "George Washington"; **Good**: ```javascript const FIRST_US_PRESIDENT = "George Washington"; - -let CURRENT_US_PRESIDENT = "Donald Trump"; -if (bool) { - CURRENT_US_PRESIDENT = "somone else"; -} ``` **[⬆ back to top](#table-of-contents)** @@ -99,16 +95,16 @@ Make your names searchable. **Bad:** ```javascript // What the heck is 525600 for? -for (let i = 0; i < 525600; i++) { +for (var i = 0; i < 525600; i++) { runCronJob(); } ``` **Good**: ```javascript -// Declare them as capitalized `const` globals. -const MINUTES_IN_A_YEAR = 525600; -for (let i = 0; i < MINUTES_IN_A_YEAR; i++) { +// Declare them as capitalized `var` globals. +var MINUTES_IN_A_YEAR = 525600; +for (var i = 0; i < MINUTES_IN_A_YEAR; i++) { runCronJob(); } ``` @@ -136,7 +132,7 @@ Explicit is better than implicit. **Bad:** ```javascript -const locations = ['Austin', 'New York', 'San Francisco']; +var locations = ['Austin', 'New York', 'San Francisco']; locations.forEach((l) => { doStuff(); doSomeOtherStuff(); @@ -150,7 +146,7 @@ locations.forEach((l) => { **Good**: ```javascript -const locations = ['Austin', 'New York', 'San Francisco']; +var locations = ['Austin', 'New York', 'San Francisco']; locations.forEach((location) => { doStuff(); doSomeOtherStuff(); @@ -168,7 +164,7 @@ variable name. **Bad:** ```javascript -const Car = { +var Car = { carMake: 'Honda', carModel: 'Accord', carColor: 'Blue' @@ -181,7 +177,7 @@ function paintCar(car) { **Good**: ```javascript -const Car = { +var Car = { make: 'Honda', model: 'Accord', color: 'Blue' @@ -198,7 +194,7 @@ function paintCar(car) { **Bad:** ```javascript function createMicrobrewery(name) { - let breweryName; + var breweryName; if (name) { breweryName = name; } else { @@ -210,7 +206,7 @@ function createMicrobrewery(name) { **Good**: ```javascript function createMicrobrewery(name) { - const breweryName = name || 'Hipster Brew Co.' + var breweryName = name || 'Hipster Brew Co.' } ``` **[⬆ back to top](#table-of-contents)** @@ -241,7 +237,7 @@ function createMenu(title, body, buttonText, cancellable) { **Good**: ```javascript -const menuConfig = { +var menuConfig = { title: 'Foo', body: 'Bar', buttonText: 'Baz', @@ -267,7 +263,7 @@ this guide other than this, you'll be ahead of many developers. ```javascript function emailClients(clients) { clients.forEach(client => { - const clientRecord = database.lookup(client); + let clientRecord = database.lookup(client); if (clientRecord.isActive()) { email(client); } @@ -290,7 +286,7 @@ function emailClientIfNeeded(client) { } function isClientActive(client) { - const clientRecord = database.lookup(client); + let clientRecord = database.lookup(client); return clientRecord.isActive(); } ``` @@ -304,7 +300,7 @@ function dateAdd(date, month) { // ... } -const date = new Date(); +let date = new Date(); // It's hard to to tell from the function name what is added dateAdd(date, 1); @@ -316,7 +312,7 @@ function dateAddMonth(date, month) { // ... } -const date = new Date(); +let date = new Date(); dateAddMonth(date, 1); ``` **[⬆ back to top](#table-of-contents)** @@ -329,19 +325,19 @@ testing. **Bad:** ```javascript function parseBetterJSAlternative(code) { - const REGEXES = [ + let REGEXES = [ // ... ]; - const statements = code.split(' '); - const tokens = []; + let statements = code.split(' '); + let tokens; REGEXES.forEach((REGEX) => { statements.forEach((statement) => { // ... }) }); - const ast = []; + let ast; tokens.forEach((token) => { // lex... }); @@ -355,15 +351,15 @@ function parseBetterJSAlternative(code) { **Good**: ```javascript function tokenize(code) { - const REGEXES = [ + let REGEXES = [ // ... ]; - const statements = code.split(' '); - const tokens = []; + let statements = code.split(' '); + let tokens; REGEXES.forEach((REGEX) => { statements.forEach((statement) => { - tokens.push( // ... ); + // ... }) }); @@ -371,17 +367,17 @@ function tokenize(code) { } function lexer(tokens) { - const ast = []; + let ast; tokens.forEach((token) => { - ast.push( // ... ); + // lex... }); return ast; } function parseBetterJSAlternative(code) { - const tokens = tokenize(code); - const ast = lexer(tokens); + let tokens = tokenize(code); + let ast = lexer(tokens); ast.forEach((node) => { // parse... }) @@ -400,10 +396,10 @@ generic functions quite easy. Take advantage of that! ```javascript function showDeveloperList(developers) { developers.forEach(developers => { - const expectedSalary = developer.calculateExpectedSalary(); - const experience = developer.getExperience(); - const githubLink = developer.getGithubLink(); - const data = { + var expectedSalary = developer.calculateExpectedSalary(); + var experience = developer.getExperience(); + var githubLink = developer.getGithubLink(); + var data = { expectedSalary: expectedSalary, experience: experience, githubLink: githubLink @@ -415,10 +411,10 @@ function showDeveloperList(developers) { function showManagerList(managers) { managers.forEach(manager => { - const expectedSalary = manager.calculateExpectedSalary(); - const experience = manager.getExperience(); - const portfolio = manager.getMBAProjects(); - const data = { + var expectedSalary = manager.calculateExpectedSalary(); + var experience = manager.getExperience(); + var portfolio = manager.getMBAProjects(); + var data = { expectedSalary: expectedSalary, experience: experience, portfolio: portfolio @@ -433,16 +429,17 @@ function showManagerList(managers) { ```javascript function showList(employees) { employees.forEach(employee => { - const expectedSalary = employee.calculateExpectedSalary(); - const experience = employee.getExperience(); - - let portfolio = employee.getGithubLink(); + var expectedSalary = employee.calculateExpectedSalary(); + var experience = employee.getExperience(); + var portfolio; if (employee.type === 'manager') { portfolio = employee.getMBAProjects(); + } else { + portfolio = employee.getGithubLink(); } - const data = { + var data = { expectedSalary: expectedSalary, experience: experience, portfolio: portfolio @@ -477,7 +474,7 @@ function writeForumComment(subject = 'No subject', body = 'No text') { **Bad:** ```javascript -const menuConfig = { +var menuConfig = { title: null, body: 'Bar', buttonText: null, @@ -497,7 +494,7 @@ createMenu(menuConfig); **Good**: ```javascript -const menuConfig = { +var menuConfig = { title: 'Order', // User did not include 'body' key buttonText: 'Send', @@ -567,7 +564,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. -let name = 'Ryan McDermott'; +var name = 'Ryan McDermott'; function splitIntoFirstAndLastName() { name = name.split(' '); @@ -584,8 +581,8 @@ function splitIntoFirstAndLastName(name) { return name.split(' '); } -const name = 'Ryan McDermott' -const newName = splitIntoFirstAndLastName(name); +var name = 'Ryan McDermott' +var newName = splitIntoFirstAndLastName(name); console.log(name); // 'Ryan McDermott'; console.log(newName); // ['Ryan', 'McDermott']; @@ -606,14 +603,14 @@ would be much better to just use ES6 classes and simply extend the `Array` globa **Bad:** ```javascript Array.prototype.diff = function(comparisonArray) { - const values = []; - const hash = {}; + var values = []; + var hash = {}; - for (let i of comparisonArray) { + for (var i of comparisonArray) { hash[i] = true; } - for (let i of this) { + for (var i of this) { if (!hash[i]) { values.push(i); } @@ -631,14 +628,14 @@ class SuperArray extends Array { } diff(comparisonArray) { - const values = []; - const hash = {}; + var values = []; + var hash = {}; - for (let i of comparisonArray) { + for (var i of comparisonArray) { hash[i] = true; } - for (let i of this) { + for (var i of this) { if (!hash[i]) { values.push(i); } @@ -674,9 +671,9 @@ const programmerOutput = [ } ]; -let totalOutput = 0; +var totalOutput = 0; -for (let i = 0; i < programmerOutput.length; i++) { +for (var i = 0; i < programmerOutput.length; i++) { totalOutput += programmerOutput[i].linesOfCode; } ``` @@ -699,7 +696,7 @@ const programmerOutput = [ } ]; -const totalOutput = programmerOutput +var totalOutput = programmerOutput .map((programmer) => programmer.linesOfCode) .reduce((acc, linesOfCode) => acc + linesOfCode, 0); ``` @@ -875,14 +872,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 (let i = 0, len = list.length; i < len; i++) { +for (var i = 0, len = list.length; i < len; i++) { // ... } ``` **Good**: ```javascript -for (let i = 0; i < list.length; i++) { +for (var i = 0; i < list.length; i++) { // ... } ``` @@ -903,7 +900,7 @@ function newRequestModule(url) { // ... } -const req = newRequestModule; +var req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); ``` @@ -914,7 +911,7 @@ function newRequestModule(url) { // ... } -const req = newRequestModule; +var req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); ``` **[⬆ back to top](#table-of-contents)** @@ -945,7 +942,7 @@ class BankAccount { } } -const bankAccount = new BankAccount(); +let bankAccount = new BankAccount(); // Buy shoes... bankAccount.balance = bankAccount.balance - 100; @@ -966,7 +963,7 @@ class BankAccount { } } -const bankAccount = new BankAccount(); +let bankAccount = new BankAccount(); // Buy shoes... bankAccount.withdraw(100); @@ -980,7 +977,7 @@ This can be accomplished through closures (for ES5 and below). **Bad:** ```javascript -const Employee = function(name) { +var Employee = function(name) { this.name = name; } @@ -988,7 +985,7 @@ Employee.prototype.getName = function() { return this.name; } -const employee = new Employee('John Doe'); +var 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 @@ -996,7 +993,7 @@ console.log('Employee name: ' + employee.getName()); // Employee name: undefined **Good**: ```javascript -const Employee = (function() { +var Employee = (function() { function Employee(name) { this.getName = function() { return name; @@ -1006,7 +1003,7 @@ const Employee = (function() { return Employee; }()); -const employee = new Employee('John Doe'); +var 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 @@ -1245,12 +1242,12 @@ function renderLargeShapes(shapes) { shape.setHeight(5); } - const area = shape.getArea(); + let area = shape.getArea(); shape.render(area); }) } -const shapes = [new Rectangle(), new Rectangle(), new Square()]; +let shapes = [new Rectangle(), new Rectangle(), new Square()]; renderLargeShapes(shapes); ``` **[⬆ back to top](#table-of-contents)** @@ -1287,7 +1284,7 @@ class DOMTraverser { } } -const $ = new DOMTraverser({ +let $ = new DOMTraverser({ rootNode: document.getElementsByTagName('body'), animationModule: function() {} // Most of the time, we won't need to animate when traversing. // ... @@ -1320,7 +1317,7 @@ class DOMTraverser { } } -const $ = new DOMTraverser({ +let $ = new DOMTraverser({ rootNode: document.getElementsByTagName('body'), options: { animationModule: function() {} @@ -1378,7 +1375,7 @@ class InventoryRequester { } } -const inventoryTracker = new InventoryTracker(['apples', 'bananas']); +let inventoryTracker = new InventoryTracker(['apples', 'bananas']); inventoryTracker.requestItems(); ``` @@ -1419,7 +1416,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. -const inventoryTracker = new InventoryTracker(['apples', 'bananas'], new InventoryRequesterV2()); +let inventoryTracker = new InventoryTracker(['apples', 'bananas'], new InventoryRequesterV2()); inventoryTracker.requestItems(); ``` **[⬆ back to top](#table-of-contents)** @@ -1432,7 +1429,7 @@ classes until you find yourself needing larger and more complex objects. **Bad:** ```javascript -const Animal = function(age) { +var Animal = function(age) { if (!(this instanceof Animal)) { throw new Error("Instantiate Animal with `new`"); } @@ -1442,7 +1439,7 @@ const Animal = function(age) { Animal.prototype.move = function() {}; -const Mammal = function(age, furColor) { +var Mammal = function(age, furColor) { if (!(this instanceof Mammal)) { throw new Error("Instantiate Mammal with `new`"); } @@ -1455,7 +1452,7 @@ Mammal.prototype = Object.create(Animal.prototype); Mammal.prototype.constructor = Mammal; Mammal.prototype.liveBirth = function() {}; -const Human = function(age, furColor, languageSpoken) { +var Human = function(age, furColor, languageSpoken) { if (!(this instanceof Human)) { throw new Error("Instantiate Human with `new`"); } @@ -1535,7 +1532,7 @@ class Car { } } -const car = new Car(); +let car = new Car(); car.setColor('pink'); car.setMake('Ford'); car.setModel('F-150') @@ -1574,7 +1571,7 @@ class Car { } } -const car = new Car() +let car = new Car() .setColor('pink') .setMake('Ford') .setModel('F-150') @@ -1697,19 +1694,19 @@ const assert = require('assert'); describe('MakeMomentJSGreatAgain', function() { it('handles 30-day months', function() { - const date = new MakeMomentJSGreatAgain('1/1/2015'); + let date = new MakeMomentJSGreatAgain('1/1/2015'); date.addDays(30); date.shouldEqual('1/31/2015'); }); it('handles leap year', function() { - const date = new MakeMomentJSGreatAgain('2/1/2016'); + let date = new MakeMomentJSGreatAgain('2/1/2016'); date.addDays(28); assert.equal('02/29/2016', date); }); it('handles non-leap year', function() { - const date = new MakeMomentJSGreatAgain('2/1/2015'); + let date = new MakeMomentJSGreatAgain('2/1/2015'); date.addDays(28); assert.equal('03/01/2015', date); }); @@ -1783,9 +1780,9 @@ require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Marti ```javascript async function getCleanCodeArticle() { try { - 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'); + 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'); await fileHandle.writeFile('article.html', response); console.log('File written'); @@ -1887,11 +1884,11 @@ they want. The point is, no matter what you all choose, just be consistent. **Bad:** ```javascript -const DAYS_IN_WEEK = 7; -const daysInMonth = 30; +var DAYS_IN_WEEK = 7; +var daysInMonth = 30; -const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; -const Artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; +var songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; +var Artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; function eraseDatabase() {} function restore_database() {} @@ -1902,11 +1899,11 @@ class Alpaca {} **Good**: ```javascript -const DAYS_IN_WEEK = 7; -const DAYS_IN_MONTH = 30; +var DAYS_IN_WEEK = 7; +var DAYS_IN_MONTH = 30; -const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; -const artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; +var songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; +var artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; function eraseDatabase() {} function restoreDatabase() {} @@ -1938,7 +1935,7 @@ class PerformanceReview { } getPeerReviews() { - const peers = this.lookupPeers(); + let peers = this.lookupPeers(); // ... } @@ -1949,7 +1946,7 @@ class PerformanceReview { } getManagerReview() { - const manager = this.lookupManager(); + let manager = this.lookupManager(); } getSelfReview() { @@ -1975,7 +1972,7 @@ class PerformanceReview { } getPeerReviews() { - const peers = this.lookupPeers(); + let peers = this.lookupPeers(); // ... } @@ -1984,7 +1981,7 @@ class PerformanceReview { } getManagerReview() { - const manager = this.lookupManager(); + let manager = this.lookupManager(); } lookupMananger() { @@ -2010,15 +2007,15 @@ Comments are an apology, not a requirement. Good code *mostly* documents itself. ```javascript function hashIt(data) { // The hash - let hash = 0; + var hash = 0; // Length of string - const length = data.length; + var length = data.length; // Loop through every character in data - for (let i = 0; i < length; i++) { + for (var i = 0; i < length; i++) { // Get character code. - const char = data.charCodeAt(i); + var char = data.charCodeAt(i); // Make the hash hash = ((hash << 5) - hash) + char; // Convert to 32-bit integer @@ -2031,11 +2028,11 @@ function hashIt(data) { ```javascript function hashIt(data) { - let hash = 0; - const length = data.length; + var hash = 0; + var length = data.length; - for (let i = 0; i < length; i++) { - const char = data.charCodeAt(i); + for (var i = 0; i < length; i++) { + var char = data.charCodeAt(i); hash = ((hash << 5) - hash) + char; // Convert to 32-bit integer @@ -2097,7 +2094,7 @@ proper indentation and formatting give the visual structure to your code. //////////////////////////////////////////////////////////////////////////////// // Scope Model Instantiation //////////////////////////////////////////////////////////////////////////////// -const $scope.model = { +let $scope.model = { menu: 'foo', nav: 'bar' }; @@ -2105,19 +2102,19 @@ const $scope.model = { //////////////////////////////////////////////////////////////////////////////// // Action setup //////////////////////////////////////////////////////////////////////////////// -const actions = function() { +let actions = function() { // ... } ``` **Good**: ```javascript -const $scope.model = { +let $scope.model = { menu: 'foo', nav: 'bar' }; -const actions = function() { +let actions = function() { // ... } ``` From 767b2f85d130922be6cae903b206d08c0abe1a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Scho=CC=88nwald?= Date: Sat, 7 Jan 2017 15:36:53 +0100 Subject: [PATCH 10/10] Reapply changes --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 94e7fa2c..c4427593 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,10 @@ var yearMonthDay = moment().format('YYYY/MM/DD'); ``` **[⬆ back to top](#table-of-contents)** -### Use ES6 constants when variable values do not change -In the bad example, the variable can be changed. -When you declare a constant, the variable should stay -the same throughout the program. - +### Use ES6 constants when variable will not be reassigned +In the bad example, the variable can be reassigned. +When you declare a constant, the variable can only be altered. +If you want to reassign a variable use `let`. **Bad:** ```javascript @@ -67,6 +66,11 @@ var FIRST_US_PRESIDENT = "George Washington"; **Good**: ```javascript const FIRST_US_PRESIDENT = "George Washington"; + +let CURRENT_US_PRESIDENT = "Donald Trump"; +if (bool) { + CURRENT_US_PRESIDENT = "somone else"; +} ``` **[⬆ back to top](#table-of-contents)**