1# JavaScript Coding Style Guide 2 3## Goal 4Rules are not perfect. Prohibiting features that are useful in specific situations can have an impact on code implementation, but we set the rules for the benefit of most programmers. If we identify a rule cannot be followed in the operations, we should work together to improve the rule. You are supposed to have the basic JavaScript language capabilities to refer to this guide, instead of learning the JavaScript language from it. 5 6## General Principles 7The code is required to be **readable, maintainable, secure, reliable, testable, efficient, and portable** on the premise that the functions are correct. 8 9## Convention 10 11**Rule**: Conventions that must be complied with during programming 12**Recommendation**: Conventions that must be considered during programming 13 14It is important to understand why this convention is so stated in both "Rules" or "Recommendations" and make efforts to comply. 15 16## Exceptions 17 18If the General Principle is not violated, the rules can be properly violated after full consideration and sufficient reasons are provided. 19Exceptions compromise code consistency so please avoid exceptions. Exceptions to "Rules" should be rare. 20 21The style consistency principle is preferred in the following situations: 22**When modifying external open-source code and third-party code, comply with the existing rules of the open-source code and third-party code and keep the style consistent. ** 23 24## Programming Regulations 25 26### Naming Regulations 27 28#### Rule 1.1 Use correct English spellings to name, no use of pinyin spellings. 29 30**Counterexample:**`xingming`,`zhanghao` 31 32**Example:**`username`,`account` 33 34#### Rule 1.2 Use abbreviations as few as possible, except for common words or professional words. For example, `context` can be shortened to `ctx`, `request` can be shortened to `req`, and `response` can be shortened to `resp`. 35 36**Note:** Complete spelling of words can avoid unnecessary misunderstanding. 37 38**Exceptions:** The variable name of the cyclic condition can be ` i` or ` j` in the cyclic language. 39 40#### Rule 1.3 Class name, enumeration name and namespace name should comply the `upperCamelCase` style. 41 42**Example:** 43 44```javascript 45// Class name 46class User { 47 constructor(username) { 48 this.username = username; 49 } 50 51 sayHi() { 52 console.log(`hi, ${this.username}`); 53 } 54} 55 56// Enumeration name 57const UserType = { 58 TEACHER: 0, 59 STUDENT: 1 60}; 61 62// Namespace 63const Base64Utils = { 64 encrypt: function(text) { 65 // todo encrypt 66 }, 67 decrypt: function(text) { 68 // todo decrypt 69 } 70}; 71``` 72 73#### Rule 1.4 Variable name, method name, and parameter name should comply the `lowerCamelCase` style. 74 75**Example:** 76 77```javascript 78let msg = 'Hello world'; 79 80function sendMsg(msg) { 81 // todo send message 82} 83 84function findUser(userID) { 85 // todo find user by user ID 86} 87``` 88 89#### Rule 1.5 The names of static constants and enumeration values must be in upper case, and words are separated by underscores (_). 90 91**Example:** 92 93```javascript 94const MAX_USER_SIZE = 10000; 95 96const UserType = { 97 TEACHER: 0, 98 STUDENT: 1 99}; 100``` 101 102#### Recommendation 1.6 Do not use negative Boolean variable names. Local variables or methods of the Boolean type must be prefixed with expressions with the meaning of right or wrong. 103 104**Counterexample:** 105 106```javascript 107let isNoError = true; 108let isNotFound = false; 109function empty() {} 110function next() {} 111``` 112 113**Example:** 114 115```javascript 116let isError = false; 117let isFound = true; 118function isEmpty() {} 119function hasNext() {} 120``` 121 122### Code Format 123 124#### Rule 2.1 Use two spaces to indent, and do not use the `tab` character. 125 126**Note:** Only spaces are allowed for indentation. Two spaces are allowed at a time. Tab characters are not allowed for indentation. 127 128**Example:** 129 130```javascript 131const dataSource = [ 132 { 133 id: 1, 134 title: 'Title 1', 135 content: 'Content 1' 136 }, 137 { 138 id: 2, 139 title: 'Title 2', 140 content: 'Content 2' 141 } 142]; 143 144function render(container, dataSource) { 145 if (!container || !dataSource || !dataSource.length) { 146 return void 0; 147 } 148 149 const fragment = document.createDocumentFragment(); 150 for (let data of dataSource) { 151 if (!data || !data.id || !data.title || !data.content) { 152 continue; 153 } 154 const element = document.createElement("div"); 155 const textNode = document.createTextNode(`${data.title}: ${data.content}`); 156 element.appendChild(textNode); 157 element.setAttribute("id", data.id); 158 fragment.appendChild(element); 159 } 160 container.appendChild(fragment); 161} 162 163``` 164 165#### Rule 2.2 The line width cannot exceed 120 characters. 166 167**Note:** It is recommended that each line should contain no more than 120 characters. Use a proper method to break the line if the line contain more than 120 characters. 168 169**Exception:** If a line of comments contains more than 120 characters of commands or URLs, keep it in one line for easy copying, pasting, and searching by running the grep command. The preprocessed error information is easy to read and understand in one line, even if it contains more than 120 characters. 170 171#### Rule 2.3 The use of braces must comply with the following conventions: 172 1731. If the value in the braces is empty, the value can be abbreviated as `{}` without a line feed. 1742. Do not use a line feed before the left brace, and use one after it. 1753. Use a line feed before the right brace, and use one after it as long as it is not followed by `else` or `catch`. 176 177#### Rule 2.4 Implementations of conditional and loop statements must be enclosed in braces, even if there is only one statement. 178 179**Counterexample:** 180 181```javascript 182if (condition) 183 console.log('success'); 184 185for(let idx = 0; idx < 5; ++idx) 186 console.log(idx); 187``` 188 189**Example:** 190 191```javascript 192if (condition) { 193 console.log('success'); 194} 195 196for(let idx = 0; idx < 5; ++idx) { 197 console.log(idx); 198} 199``` 200 201#### Rule 2.5 Condition statements and loop statements cannot be written in one line. 202 203**Counterexample:** 204 205```javascript 206if (condition) { /* todo something */ } else { /* todo other */ } 207 208let idx = 0; 209while(idx < 10) console.log(idx); 210``` 211 212**Example:** 213 214```javascript 215if (condition) { 216 /* todo something */ 217} else { 218 /* todo other */ 219} 220 221let idx = 0; 222while(idx < 10) { 223 console.log(idx); 224} 225``` 226 227#### Rule 2.6 The `case` and `default` in the `switch` statement must be indented by one layer. 228 229**Example:** 230 231```javascript 232switch(condition) { 233 case 0: 234 doSomething(); 235 break; 236 case 1: { // the braces is not necessary 237 doOtherthing(); 238 break; 239 } 240 default: 241 break; 242} 243``` 244 245#### Rule 2.7 The line feeds of expressions must be consistent, and the operator must be placed at the end of the line. 246 247**Note:** If a long expression does not meet the line width requirement, you need to wrap the line in a proper position. Generally, in the late phrase of the lower-priority operator or connector, the operator or connector should be placed at the end of the line. The operator and separator are placed at the end of the line, indicating that there is not the end. 248 249**Example:** 250 251```javascript 252// if the condition statement exceeds the line width. 253if (userCount > MAX_USER_COUNT || 254 userCount < MIN_USER_COUNT) { 255 doSomething(); 256} 257 258const sum = 259 number1 + 260 number2 + 261 number3 + 262 number4 + 263 number5 + 264 number6 + 265 number7 + 266 number8 + 267 number9; 268``` 269 270#### Rule 2.8 Multiple variable definitions and assignment statements cannot be written in one line. 271 272**Counterexample:** 273 274```javascript 275let maxCount = 10, isCompleted = false; 276 277let pointX, pointY; 278pointX = 10; pointY = 0; 279``` 280 281**Example:** 282 283```javascript 284let maxCount = 10; 285let isCompleted = false; 286 287let pointX = 0; 288let pointY = 0; 289``` 290 291#### Rule 2.9 Spaces should highlight keywords and important information. Avoid unnecessary spaces. 292 293**Note:** Spaces reduce code density and increase code readability. The general rules are as follows: 294 2951. Add a spaces after keywords `if`、`elseif`、`else`、`switch`、`while`、`for`. 2962. No space is added between the parentheses. 2973. Spaces must be added on both sides of the braces, except for simple scenarios such as `{}`. 2984. No space is added between multiple parentheses. 2995. No space is added after unary operators (`&`, `*`, `+`, `-`, `!`,etc.). 3006. Add a space on the left and right side of binary operators `=`、`+`、`-`、`*`、`/`、`%`、`|`、`&`、`||`、`&&`、`<`、`>`、`<=`、`>=`、`==`、`!=`、`===`、`!==`, etc.) 3017. Add a space on the left and right side of ternary operator (`?: `). 3028. No space is added between the preceded or post-decrease (`++`, `--`) and variables. 3039. Add a space before a comma (`, `). 30410. Add a space after `//` in a single line. 30511. No space is added at the end of the line. 306 307#### Rule 2.10 Expression statements must end with a semicolon. 308 309**Counterexample:** 310 311```javascript 312let username = 'jack' 313let birthday = '1997-09-01' 314 315console.log(`${username}'s birthday is ${birthday}`) 316``` 317 318**Example:** 319 320```javascript 321let username = 'jack'; 322let birthday = '1997-09-01'; 323 324console.log(`${username}'s birthday is ${birthday}`); 325``` 326 327#### Recommendation 2.11 Use single quotation marks to wrap strings first. 328 329**Example:** 330 331```javascript 332let message = 'world'; 333console.log(message); 334``` 335 336### Code instructions 337 338#### Rule 3.1 When declaring a variable, use the keyword `var`, `let`, or `const` to prevent the variable from being exposed to the global scope. 339 340**Note:** If the keyword `var`, `let`, or `const` is not used to declare a variable, the variable will be exposed to the global scope, which may overwrite the variable with the same name in the global scope. As a result, the GC cannot effectively reclaim the memory. In addition, when a variable contains sensitive information, exposing to the global scope may result in information leakage. ** Use `const` instead of `var` for all references; Use `let` instead of `var` if you need a variable reference.** Because the scope of `const` and `let` is smaller, writing code is easier to control. Const ensures that the reference cannot be re-assigned. The pointer referenced by const is immutable, and an error will be reported during re-assignment, avoiding overwriting. 341 342**Counterexample:** 343 344```javascript 345function open() { 346 url = 'http://127.0.0.1:8080'; //url will be exposed to the global scope 347 //todo something 348} 349open(); 350console.log(url); //url can be accessed, output: http://127.0.0.1:8080 351``` 352 353**Example:** 354 355```javascript 356function open() { 357 let url = 'http://127.0.0.1:8080'; 358 // todo something 359} 360open(); 361console.log(url); //Report: Uncaught ReferenceError: url is not defined 362``` 363 364```javascript 365function open() { 366 const url = 'http://127.0.0.1:8080'; 367 //todo something 368} 369open(); 370console.log(url); //Report: Uncaught ReferenceError: url is not defined 371``` 372 373#### Rule 3.2 Function expressions must be used to declare functions in function blocks. 374 375**Note:** Although many JS engines support in-block declaration functions, they do not belong to the ECMAScript specification. The poor implementation of browsers is incompatible with each other, and some are contrary to the future ECMAScript draft. In addition, ECMAScript5 does not support block scopes. All control flows are not independent scopes. Variables or functions declared in the control flows are in the scope of their parent functions or scripts. As a result, the declaration of functions or variables in blocks may be overwritten. If you do need to define a function in a block, you should initialize it using a function expression. 376 377**Counterexample:** 378 379```javascript 380function bar(name) { 381 if (name === "hotel") { 382 // 1. Define a foo function. The function scope is not the 'if' code block but the 'bar' function scope. 383 function foo() { 384 console.log("hotel foo A"); 385 } 386 } else { 387 // 2. Define the 'foo' function again to overwrite the 'foo' function definition under the 'if' condition branch. 388 function foo() { 389 console.log("hotel foo 2"); 390 } 391 } 392 foo && foo(); 393} 394bar("hotel"); // output is shown as"hotel foo 2" 395``` 396 397**Example:** 398 399```javascript 400function bar(name) { 401 var foo; 402 if (name == "hotel") { 403 foo = function () { 404 console.log("hotel foo 1"); 405 }; 406 } else { 407 foo = function () { 408 console.log("hotel foo 2"); 409 } 410 } 411 foo && foo(); 412} 413bar("hotel"); // Correct output"hotel foo 1" 414``` 415 416#### Rule 3.3 Encapsulation of Basic Types is prohibited 417 418**Note:** JavaScript has five basic data types: Undefined, Null, Boolean, Number, and String. The value of the base data type is unchangeable. The basic data type object used in JavaScript is only a value. It does not contain the methods and attributes of the object encapsulated by the object. When the attributes and methods are not required, the encapsulation type of the object does not need to be used. 419 420**Counterexample:** 421 422```javascript 423var isShow = new Boolean(false); 424if (isShow) { 425 alert('hi'); //It is executed, and the following information is displayed: hi 426} 427``` 428 429**Example:** 430 431```javascript 432var isShow = false; 433if (isShow) { 434 alert('hi'); 435} 436``` 437 438#### Rule 3.4 The use of `with` is prohibited 439 440**Note:** Using 'with' makes your code semantically unclear, because objects of 'with' may conflict with local variables, changing the original meaning of the program. 441 442**Counterexample:** 443 444```javascript 445var foo = { x: 5 }; 446with(foo) { 447 var x = 3; 448 console.log(x); //Output: 5 449} 450``` 451 452#### Rule 3.5 `this` can only be used in object constructors, methods, and closures. 453 454**Note:** In JavaScript, the "this" pointer represents the owner of the object that executes the current code. This has special semantics: 455 456+ Global objects (in most cases) 457+ Scope of the caller (when eval is used) 458+ Nodes in the DOM tree (when adding event handling functions) 459+ Newly created object (using a constructor) 460+ Other objects (if the function is called() or apply()) 461 462```javascript 463var User = function(username) { 464 this.username = username; 465}; 466var user = new User('John'); 467console.log(user.username); // Output: John 468 469var ClickCounter = { 470 value: 0, 471 click: function() { 472 ++this.value; 473 }, 474 getValue() { 475 return this.value; 476 } 477}; 478console.log(Counter.getValue()); //Output: 0 479Counter.click(); 480console.log(Counter.getValue()); //Output: 1 481``` 482 483#### Rule 3.6 Do not use conditional comments in IE. 484 485**Note:** Conditional compilation can be activated using the `\@cc_on` statement or the `\@if` or `\@set` statement in IE. Although comments can be made to be compatible with browsers other than IE, they hinder the execution of automation tools because they change the JavaScript syntax tree at run time. 486 487**Counterexample:** 488 489```javascript 490var f = function () { 491 /*@cc_on @*/ 492 /*@if (@_jscript_version >= 4) 493 alert("JavaScript version 4 or better"); 494 @else @*/ 495 alert("Conditional compilation not supported by this scripting engine."); 496 /*@end @*/ 497}; 498``` 499 500#### Rule 3.7 Prototypes of built-in objects cannot be modified. 501 502**Note:** As a set of public interfaces, built-in objects have conventional behaviors. Modifying the prototype may damage the interface semantics or cause abnormalities during debugging. 503 504**Counterexample:** 505 506```javascript 507Array.prototype.indexOf = function () { return -1 } 508var arr = [1, 1, 1, 1, 1, 2, 1, 1, 1]; 509console.log(aar.indexOf(2)); // Output:-1 510``` 511 512#### Rule 3.8 Do not directly use the built-in attribute of `Object.prototype`. 513 514**Note:** ECMAScript 5.1 adds `Object.create`, which creates a new object and uses an existing object to provide the proto of the newly created object. `Object.create(null)` is a common pattern for creating objects used as maps. Unexpected behavior or vulnerability may occur when the object has an attribute with the same name as `Object.prototype`. For example, it is not safe for a web server to parse JSON input from a client and use `hasOwnProperty` to directly invoke the generated object, because a malicious client may send a similar JSON value `' {"hasOwnProperty": 1} '` and cause the server to crash. 515 516**Counterexample:** 517 518```javascript 519var hasBarProperty = foo.hasOwnProperty("bar"); 520var isPrototypeOfBar = foo.isPrototypeOf(bar); 521var barIsEnumerable = foo.propertyIsEnumerable("bar"); 522``` 523 524**Example:** 525 526```javascript 527var hasBarProperty = Object.prototype.hasOwnProperty.call(foo, "bar"); 528var isPrototypeOfBar = Object.prototype.isPrototypeOf.call(foo, bar); 529var barIsEnumerable = {}.propertyIsEnumerable.call(foo, "bar"); 530``` 531 532#### Rule 3.9 Use the `Object.getPrototypeOf` function instead of `_proto_` 533 534**Note:** ES5 introduces the `Object.getPrototypeOf` function as the standard API for obtaining object prototypes, but a large number of JavaScript engines have long used a special `proto' attribute to achieve the same purpose. However, `proto` is essentially an internal attribute rather than a formal external API. Currently, this attribute must be deployed in browsers, but not in other running environments. Therefore, this attribute is not fully compatible. For example, objects with null prototypes are handled differently in different environments. 535 536```javascript 537var empty = Object.create(null); 538"_proto_" in empty; //Some environments false is returned, some environments true is returned. 539``` 540 541Therefore, use `Object.getPrototypeOf()` instead of using the proto attribute in terms of semantics and compatibility. The `Object.getPrototypeOf' function is valid in any environment and is a more standard and portable method for extracting object prototypes. 542 543#### Rule 3.10 Do not create functions with function constructors. 544 545**Note:** There are three methods for defining a function: function declaration, function constructor, and function expression. Regardless of in which method you define a function, they are instances of the Function object and inherit all default or custom methods and properties of the Function object. The method of creating a function using a function constructor is similar to the character string `eval()`. Any character string can be used as the function body, which may cause security vulnerabilities. 546 547**Counterexample:** 548 549```javascript 550var func = new Function('a', 'b', 'return a + b'); 551var func2 = new Function('alert("Hello")'); 552``` 553 554**Example:** 555 556```javascript 557function func(a, b) { 558 return a + b; 559} 560 561var func2 = function(a, b) { 562 return a + b; 563} 564``` 565 566#### Suggestion 3.11 When using the prototype `prototype' to implement inheritance, try to use the existing stable library methods instead of self-implementing them. 567 568**Note:** The multi-level prototype structure refers to the inheritance relationship in JavaScript. When you define a class D and use class B as its prototype, you get a multilevel prototype structure. These prototype structures can get complicated. Using existing stable library methods such as `goog.inherits()` of the Closure library or other similar functions can avoid unnecessary coding errors. 569 570#### Suggestion 3.12 When defining a class, you should define the method under the prototype and the attributes within the constructor. 571 572**Note:** There are multiple methods in JavaScript to add methods or members to constructors. However, using a prototype to define methods can reduce memory usage and improve running efficiency. 573 574**Counterexample:** 575 576```javascript 577function Animals() { 578 this.walk = function() {}; // This causes a walk method to be created on each instance. 579} 580``` 581 582**Example:** 583 584```javascript 585function Animals() {} 586 587Animals.prototype.walk = function() {}; 588``` 589 590#### Suggestion 3.13 When using closures, avoid cyclic reference, which may cause memory leakage. 591 592**Note:** 593JavaScript is a garbage collection language in which the memory of an object is allocated to the object based on its creation and is reclaimed by the browser when there is no reference to the object. JavaScript's garbage collection mechanism is fine on its own, but browsers are somewhat different in the way they allocate and recover memory for DOM objects. Both IE and Firefox use reference counting to process memory for DOM objects. In the reference counting system, each referenced object keeps a count to see how many objects are referencing it. If the count is zero, the object is destroyed and the memory it occupies is returned to the heap. While this solution is generally effective, there are some blind spots in circular references. When two objects refer to each other, they form a circular reference, where the reference counting values of the objects are assigned to 1. In pure garbage collection systems, circular references are not a problem: if one of the two objects involved is referenced by any other object, both objects will be garbage collected. In a reference counting system, neither of these objects can be destroyed because reference counting can never be 0. In a hybrid system that uses both garbage collection and reference counting, a leak occurs because the system does not correctly recognize circular references. In this case, neither the DOM object nor the JavaScript object can be destroyed. Circular references are easy to create. Circular references are particularly prominent in closures, one of JavaScript's most convenient programming structures. Closures hold references to their external scopes (including local variables, parameters, and methods). When the closure itself is held by scope members (usually DOM objects), circular references are formed, which further leads to memory leaks. 594 595**Counterexample:** 596 597```javascript 598function setClickListener(element, a, b) { 599 element.onclick = function() { 600 // Use a and b here 601 }; 602}; 603``` 604 605In the above code, the closure retains references to elements, a, and b even if element is not used. Because the element also retains the reference to the closure, a circular reference is generated and cannot be recycled by the GC. 606 607**Example:** 608 609```javascript 610function setClickListener(element, a, b) { 611 element.onclick = createHandler(a, b); 612} 613 614function createHandler(a, b) { 615 // By adding another function to avoid the closure itself, you can organize memory leaks. 616 return function() { 617 // Use a and b here 618 } 619} 620``` 621 622#### Suggestion 3.14 Watch out for JavaScript floating point numbers. 623 624**Note:** JavaScript has a single numeric type: `IEEE 754` double-precision floating point number. Having a single numeric type is one of the best features of JavaScript. Multiple number types can be a source of complexity, confusion and error. However, one of the biggest drawbacks of the binary floating-point type is that it does not accurately represent the fractional part, causing unexpected precision problems, as shown in the following examples. 625 626Sample Code1: 627 628```javascript 629console.log(0.1 + 0.2 === 0.3); // Output: false. Therefore, do not use == or === to compare floating-point numbers. 630``` 631 632Sample Code2: 633 634```javascript 635var sum1 = (0.1 + 0.2) + 0.3; 636console.log(sum1); // Output: 0.6000000000000001 637 638var sum2 = 0.1 + (0.2 + 0.3); 639console.log(sum2); // Output: 0.6. Therefore, for binary floating-point numbers, (a + b) + c cannot be guaranteed to produce the same result as a + (b + c). 640``` 641 642The effective solutions are as follows: 643 6441. Use integers as much as possible because integers do not need to be rounded. 645 6462. The native JavaScript method `Number.prototype.toFixed(digits)`,`digits` is used to indicate the number of digits after the decimal point. The exponential method is not used. If necessary, the number is rounded off. This method is used to reduce the precision of the calculation result before determining the floating-point number calculation result. The sample code is as follows: 647 648 ```javascript 649 parseFloat(0.1 + 0.2).toFixed(1); //0.3 650 ``` 651 6523. A very small constant `Number.EPSILON =.220446049250313e-16 ` is added to ES6, which is about 0.00000000000000022204. `Number.EPSILON` is used to determine the calculation error of floating-point numbers. If the calculation error of floating-point numbers is less than or equal to the value of `Number.EPSILON`, such an error is acceptable. The sample code is as follows: 653 654 ```javascript 655 function isNumberEquals(one, other) { 656 return Math.abs(one - other) < Number.EPSILON; 657 } 658 var one = 0.1 + 0.2; 659 var other = 0.3; 660 console.log(isNumberEquals(one, other)); // Output: true 661 ``` 662 6634. Use some class library methods that support precise calculation, such as `math.js`. 664 665 ```html 666 <!DOCTYPE html> 667 <html> 668 <head> 669 <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.0.0/math.js"></script> 670 <script type="text/javascript"> 671 function fn_click() { 672 math.config({ 673 number: "BigNumber", 674 }); 675 var result = math.add(math.bignumber(0.1), math.bignumber(0.2)); 676 alert(result); 677 } 678 </script> 679 </head> 680 <body> 681 <input type="button" value="mathjs(0.1+0.2)" onclick="fn_click();" /> 682 </body> 683 </html> 684 685 ``` 686 687#### Suggestion 3.15 Do not use the array constructor with variable arguments. 688 689**Note:** The method of constructor `new Array` is not recommended to construct a new array. If the constructor has only one parameter, exceptions may occur. In addition, the global definition of the array may be modified. Therefore, it is recommended to use the array literal notation, that is, `[]` notation, to create an array. 690 691**Counterexample:** 692 693```javascript 694const arr1 = new Array(x1, x2, x3); 695const arr2 = new Array(x1, x2); 696const arr3 = new Array(x1); 697const arr4 = new Array(); 698``` 699 700Except for the third case, all other functions can work properly. If `x1` is an integer, `arr3` is an array whose length is `x1` and values are `undefined`. If `x1` is any other number, an exception is thrown, and if it is anything else, it is an array of cells. 701 702**Example:** 703 704```javascript 705const arr1 = [x1, x2, x3]; 706const arr2 = [x1, x2]; 707const arr3 = [x1]; 708const arr4 = []; 709``` 710 711This way, you'll save a lot of trouble. 712 713Similarly, use `{}` instead of `new Object()` to create objects. 714 715#### Rule 3.16 String templates are preferred over string links when constructing strings. 716 717**Note:** The template character strings are more concise and readable. 718 719**Counterexample:** 720 721```javascript 722function sayHi(name) { 723 console.log('hi, ' + name); 724} 725``` 726 727**Example:** 728 729```javascript 730function sayHi(name) { 731 console.log(`hi, ${name}`); 732} 733``` 734 735#### Rule 3.17 Use `for...of` for array traversal and `for...in` for object traversal. 736 737**Counterexample:** 738 739```javascript 740let numbers = [1, 2, 3, 4]; 741let sum = 0; 742for (let number in numbers) { 743 sum += number; 744} 745// sum === 00123; 746``` 747 748**Example:** 749 750```javascript 751let numbers = [1, 2, 3, 4]; 752let sum = 0; 753for (let number of numbers) { 754 sum += number; 755} 756// sum === 10 757``` 758 759