惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Forbes - Security
Forbes - Security
C
CERT Recently Published Vulnerability Notes
The Last Watchdog
The Last Watchdog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Secure Thoughts
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
Troy Hunt's Blog
N
News | PayPal Newsroom
人人都是产品经理
人人都是产品经理
S
Securelist
J
Java Code Geeks
月光博客
月光博客
博客园 - 叶小钗
云风的 BLOG
云风的 BLOG
Hugging Face - Blog
Hugging Face - Blog
T
Threatpost
H
Hacker News: Front Page
Recent Commits to openclaw:main
Recent Commits to openclaw:main
小众软件
小众软件
大猫的无限游戏
大猫的无限游戏
PCI Perspectives
PCI Perspectives
T
The Blog of Author Tim Ferriss
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
GbyAI
GbyAI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
量子位
SecWiki News
SecWiki News
有赞技术团队
有赞技术团队
TaoSecurity Blog
TaoSecurity Blog
N
Netflix TechBlog - Medium
Latest news
Latest news
博客园_首页
L
LINUX DO - 最新话题
V
Visual Studio Blog
G
Google Developers Blog
P
Palo Alto Networks Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Tenable Blog
Simon Willison's Weblog
Simon Willison's Weblog
Scott Helme
Scott Helme
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Privacy International News Feed
Recorded Future
Recorded Future
Stack Overflow Blog
Stack Overflow Blog
O
OpenAI News
T
Tor Project blog
IT之家
IT之家
S
SegmentFault 最新的问题

Dmitri Pavlutin Blog

Pure Functions in JavaScript: A Beginner's Guide Record Type in TypeScript: A Quick Intro How to Write Comments in React: The Good, the Bad and the Ugly 4 Ways to Create an Enum in JavaScript React forwardRef(): How to Pass Refs to Child Components TypeScript Function Types: A Beginner's Guide How to Use v-model to Access Input Values in Vue Mastering Vue refs: From Zero to Hero Environment Variables in JavaScript: process.env 5 Must-Know Differences Between ref() and reactive() in Vue How to Destructure Props in Vue (Composition API) Triangulation in Test-Driven Development How to Use nextTick() in Vue Programming to Interface Vs to Implementation A Smarter JavaScript Mapper: array.flatMap() Array Grouping in JavaScript: Object.groupBy() How to Access ES Module Metadata using import.meta JSON Modules in JavaScript How to Trim Strings in JavaScript TypeScript Function Overloading How to Debounce and Throttle Callbacks in Vue How to Show/Hide Elements in Vue Sparse vs Dense Arrays in JavaScript How to Fill an Array with Initial Values in JavaScript Covariance and Contravariance in TypeScript What are Higher-Order Functions in JavaScript? How to Use TypeScript with React Components Index Signatures in TypeScript How to Use React useReducer() Hook unknown vs any in TypeScript A Guide to React Context and useContext() Hook How to Use Promise.any() 2 Ways to Remove a Property from an Object in JavaScript 'return await promise' vs 'return promise' in JavaScript How to Use Promise.allSettled() How to Use fetch() with JSON JavaScript Promises: then(f,f) vs then(f).catch(f) What is a Promise in JavaScript? How to Use Promise.all() A Simple Guide to Component Props in React Don't Stop Me Now: How to Use React useTransition() hook A Simple Explanation of JavaScript Variables: const, let, var ES Modules Dynamic Import How to Memoize with React.useMemo() How to Cleanup Async Effects in React Why Math.max() Without Arguments Returns -Infinity How to Debounce and Throttle Callbacks in React Don't Confuse Function Expressions and Function Declarations in JavaScript How to Use ES Modules in Node.js Solving a Mystery Behavior of parseInt() in JavaScript How to Use Array Reduce Method in JavaScript 3 Ways to Merge Arrays in JavaScript A Guide to Jotai: the Minimalist React State Management Library The Difference Between Values and References in JavaScript How to Implement a Queue in JavaScript A Helpful Algorithm to Determine "this" value in JavaScript React useRef() Hook Explained in 3 Steps 7 Interview Questions on "this" keyword in JavaScript. Can You Answer Them? How to Greatly Enhance fetch() with the Decorator Pattern 7 Interview Questions on JavaScript Closures. Can You Answer Them? What's a Method in JavaScript? array.sort() Does Not Simply Sort Numbers in JavaScript How to Solve the Infinite Loop of React.useEffect() The New Array Method You'll Enjoy: array.at(index) What's the Difference between DOM Node and Element? Why Promises Are Faster Than setTimeout()? Everything About Callback Functions in JavaScript How React Updates State 5 Mistakes to Avoid When Using React Hooks 5 Best Practices to Write Quality JavaScript Variables Type checking in JavaScript: typeof and instanceof operators 3 Ways to Check if a Variable is Defined in JavaScript React Forms Tutorial: Access Input Values, Validate, Submit Forms Prototypal Inheritance in JavaScript How to Timeout a fetch() Request How to Learn JavaScript If You're a Beginner A Simple Explanation of React.useEffect() A Simple Explanation of JavaScript Iterators How to Use React Controlled Inputs Everything about null in JavaScript How to Use Fetch with async/await Getting Started with Arrow Functions in JavaScript An Interesting Explanation of async/await in JavaScript Front-end Architecture: Stable and Volatile Dependencies Is it Safe to Compare JavaScript Strings? How to Access Object's Keys, Values, and Entries in JavaScript What Actually is a String in JavaScript? 3 Ways to Shallow Clone Objects in JavaScript (w/ bonuses) Checking if an Array Contains a Value in JavaScript JavaScript Event Delegation: A Beginner's Guide How to Parse URL in JavaScript: hostname, pathname, query, hash 3 Ways to Detect an Array in JavaScript How to Get the Screen, Window, and Web Page Sizes in JavaScript 3 Ways to Check If an Object Has a Property/Key in JavaScript How to Compare Objects in JavaScript Object.is() vs Strict Equality Operator in JavaScript Own and Inherited Properties in JavaScript 5 Differences Between Arrow and Regular Functions How to Use Object Destructuring in JavaScript Your Guide to React.useCallback()
5 JavaScript Bad Coding Habits to Unlearn Right Now
Dmitri Pavlutin · 2019-07-10 · via Dmitri Pavlutin Blog

When reading JavaScript code, have you ever had the feeling:

  • that you barely understand what the code does?
  • the code uses lots of JavaScript tricks?
  • the naming and coding style are rather random?

These are the signs of bad coding habits.

In this post, I describe 5 common bad coding habits in JavaScript. And importantly I will present my actionable recommendations on how to get rid of these habits.

1. Don't use implicit type conversion

JavaScript is a loosely typed language. If used correctly, this is a benefit because of the flexibility it gives you.

Most of the operators + - * / == (but not ===) when working with operands of different types use implicit conversion of types.

The statements if (condition) {...}, while(condition) {...} implicitly transform the condition to a boolean.

The following examples rely on the implicit conversion of types. I bet you feel the confusion:


console.log("2" + "1"); // => "21"

console.log("2" - "1"); // => 1

console.log('' == 0); // => true

console.log(true == []); // -> false

console.log(true == ![]); // -> false


Relying excessively on the implicit type conversion is a bad habit. First of all, it makes your code less stable in edge cases. Secondly, you increase the chance to introduce a bug that is difficult to reproduce and fix.

Let's implement a function that gets the property of an object. If the property does not exist, the function returns a default value:


function getProp(object, propertyName, defaultValue) {

if (!object[propertyName]) {

return defaultValue;

}

return object[propertyName];

}

const hero = {

name: 'Batman',

isVillian: false

};

console.log(getProp(hero, 'name', 'Unknown')); // => 'Batman'


getProp() reads the value of the name property, which is 'Batman'.

What about trying to access isVillian property:


console.log(getProp(hero, 'isVillian', true)); // => true


That's an error. Even if the hero's property isVillian is false, the function getProp() returns the incorrect true.

It happens because the verification of property existence relies on implicit conversion to a boolean by the if (!object[propertyName]) {...}.

These kind of errors are difficult to spot. To fix the function, verify explicitely the type of the value:


function getPropFixed(object, propertyName, defaultValue) {

if (object[propertyName] === undefined) {

return defaultValue;

}

return object[propertyName];

}

const hero = {

name: 'Batman',

isVillian: false

};

console.log(getPropFixed(hero, 'isVillian', true)); // => false


object[propertyName] === undefined verifies exactly if the property accessor evaluates to undefined.

Do you know other ways to verify the property existence in an object? If so, leave a comment below!

Side note: the section 4. suggests to avoid using directly undefined. So the above solution can be improved in favor of in operator:


function getPropFixedBetter(object, propertyName, defaultValue) {

if (!(propertyName in object)) {

return defaultValue;

}

return object[propertyName];

}


Here's my advice: whenever possible, do not use implicit type conversion. Instead, make sure that variables and function parameters always have the same type. Use explicit type conversion when necessary.

A list of best practices:

  • Always use strict equality operator === to perform comparisons
  • Don't use loose equality operator ==
  • Addition operator operand1 + operand2: both operands should be numbers or both strings
  • Arithmetic operators - * / % **: both operands should be numbers
  • if (condition) {...}, while (condition) {...}, etc statements: condition should be a boolean

You might say that this approach requires writing more code... You're right! But with an explicit approach, you control the behavior of your code. Plus, the explicitness increases readability.

2. Don't use old JavaScript tricks

What's interesting about JavaScript is its creators weren't expecting the language to become so popular.

The complexity of the applications built on JavaScript was increasing faster than the language evolution. This situation forced developers to use JavaScript hacks and workarounds, just to make things work.

A classic example is searching whether an array contains an item. I've never liked to use array.indexOf(item) !== -1 to check the presence of an item.

ECMAScript 2015 and beyond are way more powerful. You can safely refactor a lot of tricks by using new language features.

Use includes() instead of indexOf() in to verify the element existence in JavaScript

Refactor array.indexOf(item) !== -1 in favor of the new ES2015 method array.includes(item).

Follow my compiled list of refactorings to remove old hacks from your JavaScript code.

3. Don't pollute the function scope

Before ES2015, JavaScript variables where function scoped. Because of that, you might developed a bad habit of declaring all the variables as function scoped.

Let's look at an example:


function someFunc(array) {

var index, item, length = array.length;

/*

* Lots of code

*/

for (index = 0; index < length; index++) {

item = array[index];

// Use `item`

}

return someResult;

}


The variables index, item and length are function scoped. But these variables pollute the function scope because they are necessary only inside the for() block scope.

With the introduction of block scope variables let and const, you should limit the life of your variables as much as possible.

Let's clean up the function scope:


function someFunc(array) {

/*

* Lots of code

*/

const length = array.length;

for (let index = 0; index < length; index++) {

const item = array[index];

// Use `item`

}

return someResult;

}


index and item variables are limited to for() cycle block scope. length was moved near the place of its usage.

The refactored code is easier to understand because the variables are not spread across the entire function scope. They exist near the place of usage.

Define the variables in the block scope they are used:

if block scope


// Bad

let message;

// ...

if (notFound) {

message = 'Item not found';

// Use `message`

}



// Good

if (notFound) {

const message = 'Item not found';

// Use `message`

}


for block scope


// Bad

let item;

for (item of array) {

// Use `item`

}



// Good

for (const item of array) {

// Use `item`

}


4. Try to avoid undefined and null

A variable not yet assigned with value is evaluated to undefined. For example:


let count;

console.log(count); // => undefined

const hero = {

name: 'Batman'

};

console.log(hero.city); // => undefined


count variable is defined, but not yet initialized with a value. JavaScript implicitly assigns to it undefined.
When accessing a non-existing property hero.city, undefined is returned also.

Why is using directly undefined a bad habit? Because when you start comparing against undefined, you're working with variables in an uninitialized state.

Variables, object properties, arrays must be initialized with values before using them!

JavaScript offers a lot of possibilities to avoid comparing with undefined.

Property existence


// Bad

const object = {

prop: 'value'

};

if (object.nonExistingProp === undefined) {

// ...

}



// Good

const object = {

prop: 'value'

};

if ('nonExistingProp' in object) {

// ...

}


Object's default properties


// Bad

function foo(options) {

if (object.optionalProp1 === undefined) {

object.optionalProp1 = 'Default value 1';

}

// ...

}



// Good

function foo(options) {

const defaultProps = {

optionalProp1: 'Default value 1'

};

options = {

...defaultProps,

...options

};

// ...

}


Default function parameter


// Bad

function foo(param1, param2) {

if (param2 === undefined) {

param2 = 'Some default value';

}

// ...

}



// Good

function foo(param1, param2 = 'Some default value') {

// ...

}


null is an indicator of a missing object.

You should strive to avoid returning null from functions, and more importantly, call functions with null as an argument.

As soon as null appears in your call stack, you have to check for its existence in every function that potentially can access null. It's error-prone.


function bar(something) {

if (something) {

return foo({ value: 'Some value' });

} else {

return foo(null);

}

}

function foo(options) {

let value = null;

if (options !== null) {

value = options.value;

// ...

}

return value;

}


Try to write code that does not involve null. Possible alternatives are try/catch mechanism, the usage of default objects.

Tony Hoare, the inventor of ALGOL, once stated:

I call it my billion-dollar mistake... [...] I was designing the first comprehensive type system for references in an object-oriented language. [...] But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.

The post "The worst mistake of computer science" goes in-depth why null is damaging the quality of your code.

5. Don't use a casual coding style. Enforce a standard

What could be more daunting than reading code that has a random coding style? You never know what to expect!

What if the codebase contains different coding styles of many developers? An assorted character graffiti wall.

Different coding styles

The same coding style across the entire team and the application codebase is a requirement. It's a boost for the code readability.

Examples of useful coding styles:

But I'll be honest with you. I'm lazy. When I'm on a deadline, or I'm about to commit before going home - I might "forget" about styling my code.

“Myself lazy” says: leave the code as is, update it later. But later means never.

I recommend to automate the process of coding style verification:

  1. Install eslint
  2. Configure eslint with a coding style that's best for you
  3. Set a pre-commit hook that runs eslint verification before committing.

Start with eslint-prettier-husky-boilerplate.

6. Conclusion

Writing quality and clean code requires discipline, overcome bad coding habits.

JavaScript is a permissive language, with a lot of flexibility. But you have to pay attention to what features you use. My recommendation is to avoid implicit type conversions and reduce the usage of undefined and null.

The language is evolving quite fast these days. Identify tricky code, and refactor it to use the latest JavaScript features.

A consistent coding style across the codebase benefits readability.

Good coding skills are always a win solution.

What other bad coding habits in JavaScript do you know?