Categories
JavaScript Mistakes

JavaScript Mistakes — Strict Mode

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at the benefits of using the strict mode directive.

Add Use Strict Mode Directive in Our Scripts

If we’re using old-school JavaScript script files, then we should add the 'use strict' directive into the top of our script.

Strict mode eliminates lots of silent errors by changing them to throw errors.

It also fixes mistakes that make optimizing our JavaScript code hard to increase their performance.

Also, it bans syntax that may be used in future JavaScript versions. Keywords like class can’t be used to declare variables, for example.

Strict mode can be applied to the whole script by putting the directive at the top or just in the function level by putting it in functions.

However, we should just apply it everywhere since it brings lots of benefits.

For instance, we can’t declare variables accidentally with 'use strict' on:

'use strict';
x = 1;

Since we have the 'use strict' directive on top of our script, we’ll get an error with the x = 1 expression since we haven’t declared x yet.

Without strict mode, this would create a global variable called x and assign 1 to it and pollute the global scope.

That isn’t good because it may overwrite another global variable with the same name.

Also, we can assign values to another global value like undefined or Infinity :

With strict mode on, code like the following will throw a TypeError:

var undefined = 1;
var Infinity = 1;

Assigning values to a non-writable property will also fail with a TypeError thrown:

var obj = {};
Object.defineProperty(obj, 'foo', { value: 42, writable: false });
obj.foo = 9;

We also wouldn’t be able to add properties that has preventExtensions called on it to prevent that:

var obj = {};
Object.preventExtensions(obj);
obj.foo = 'a';

The code above would throw a TypeError.

Attempting to delete undeletable properties will also throw an error. If we write something like:

'use strict';
delete Object.prototype;

Then we’ll get a TypeError.

Strict mode also requires function parameters to be unique. For instance, if we write:

'use strict';
function add(a, a, c) {
  return a + a + c;
}

Then we’ll get an ‘Uncaught SyntaxError: Duplicate parameter name not allowed in this context’ error since we have JavaScript strict mode on.

Also, it prevents numbers with a leading 0 from being used. The leading zero for octal numbers is rarely used and developers often assume that it’s still a decimal number.

Therefore if we have the following the strict mode throws an error:

'use strict';
var sum = 015 + 222;

If we run that, we get ‘Uncaught SyntaxError: Octal literals are not allowed in strict mode.’

The with statement is prohibited in strict mode. With strict mode, confusing code like this is prohibited:

'use strict';
var x = 17;
with(obj) {
  console.log(x);
}

The code above is confusing because x can either be obj.x or just x . It’s hard to tell what it’s referring to.

With strict mode on as we have above, we get ’Uncaught SyntaxError: Strict mode code may not include a with statement’.

Doing anything to arguments or eval will also return syntax errors, so code like the following:

'use strict';
eval = 'foo';
arguments++;

Then we get ‘Uncaught SyntaxError: Unexpected eval or arguments in strict mode’ when we run the code above since we have JavaScript strict mode on.

We shouldn’t use these entities regardless of whether JavaScript strict mode is on, so it’s good that strict mode prevents expressions like these from running at least.

With strict mode on, the this value passed into call , apply , or bind aren’t boxed into an object.

Therefore, the original value is preserved if we pass in a primitive value. For instance, if we have:

'use strict';

function fn() {
  return this;
}
console.log(fn.call(1) === 1);

Then we get 1 returned from fn instead of new Number(1) , so we get that the console log output returns true .

Strict mode is enabled automatically for modules so we don’t need the directive on top of our code.

Conclusion

With so many benefits to strict mode, we should always enable it in old-school scripts.

If we use JavaScript modules, then it’s enabled by default, so we don’t have to worry about it.

We just have to put 'use strict' on top of all our scripts.

Categories
JavaScript Mistakes

JavaScript Mistakes — Wrappers and Objects

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at bad constructs that we shouldn’t use, like manually create wrapper objects for primitive values, octal literals, and assigning parameters to a different value.

No Primitive Wrapper Instances

For strings, numbers, and boolean, we shouldn’t create wrapper objects manually with the new operator.

They’re needed so that we can call methods of primitive values, where the JavaScript interpreter will automatically create the wrapper and then call the methods. Once it’s done calling the method we want to call, then they’re automatically destroyed.

However, there’s no reason to create them manually. They’re confusing since they have the type 'object' .

For instance, if we have the following expressions:

typeof new String("foo");
typeof new Number(3);
typeof new Boolean(false);

Then they’ll all return type 'object' even though we work with them as we do with their primitive counterpart.

To convert them back to primitive values, we’ve to call the valueOf method on them as follows:

new String("foo").valueOf();
new Number(3).valueOf();
new Boolean(false).valueOf();

to get back the primitive version of those wrapper objects.

We should instead write them out as primitive value literals as follows:

"foo"
3
false

It’s less typing and there’s no confusion about the types.

No Octal Literals

Octal number literals are any numbers that start with a 0. JavaScript treats anything that starts with a 0 as an octal number.

Therefore, 051 is actually 41 in decimal.

This is a source of confusion, so octal numeric literals are deprecated in ES5.

Therefore, if we want to write 51 in our code, then we shouldn’t have a 0 before it.

No Reassignment of Function Parameters

We shouldn’t reassign function parameters to a different value in JavaScript because it’ll mutate the arguments object. This means that the actual parameters are modified.

It’s easy to make mistakes by reassigning function parameters to a new value. And it makes errors hard to track down.

For instance, we should write code like:

const foo = (x) => {
  x = 13;
}

const foo = (x) => {
  for (x of baz) {}
}

Instead, we should assign the parameter to a variable inside the function body and then manipulate it as we do in the following code:

const foo = (x) => {
  let y = x;
}

const foo = (x) => {
  for (const b of baz) {}
}

Don’t Use the __proto__ Property to Access the Prototype of the Given Object

We shouldn’t use the __proto__ property to access the prototype of the object that we’re trying to access this property on.

Instead, we can use the Object.getPrototypeOf method to access the prototype of the current object.

For instance, instead of writing:

const obj = {};
console.log(obj.__proto__)

We should write:

const obj = {};
console.log(Object.getPrototypeOf(obj))

No Variable Redeclaration

Redeclaring variables are bad. However, it’s possible to do this if we use the var keyword to declare our variables. We don’t want that to happen because we don’t which value our variable actually has.

For instance, if we have:

var a = 3;
var a = 2;

Then we get that a is 2 when we log a below the last line.

Instead, we should declare a variable with let , then we would get an error is we try to declare 2 variables with 2 different names.

Photo by Kae Ng on Unsplash

No Assignment in return Statement

In JavaScript, we can do an assignment operation in the same line as the return statement.

For instance, we can write something like:

const baz = (bar) => {
  return foo = bar + 2;
}

In the code above, we have the bar parameter and we add 2 to it. Then we assigned the sum to foo and then returned it.

Therefore foo is 5 and we returned that. However, it might also be a typo because the developer may mean to write == or === instead of = .

To make things clearer, we should put an assignment expression on a different line than the return statement.

We can also put parentheses around the assignment expression to make everyone clear that we’re assigning the value to the left operand first and then returning the left operand as the value.

So we can write:

const baz = (bar) => {
  return foo == bar + 2;
}

const baz = (bar) => {
  return foo === bar + 2;
}

const baz = (bar) => {
  return (foo = bar + 2);
}

instead of what we have above.

Conclusion

We shouldn’t use wrapper objects for primitive values since there’s no value to creating them manually. It only brings confusion to other developers and requires more typing.

Also, we shouldn’t have octal literals in our JavaScript code since they’ve deprecated.

We shouldn’t declare variables with the same name more than once.

Finally, assignment expressions shouldn’t be in return statements to reduce chance ambiguity.

Categories
JavaScript Mistakes

JavaScript Mistakes — Clumsy and Useless Expressions

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at some clumsy or useless expressions that shouldn’t be in our JavaScript code including useless blocks, magic numbers, multiline strings, and spaces, and using new without assigning the returned object.

Unnecessary Nested Blocks

Since ES2015, we can define blocks to segregate our code. They’re denoted by curly braces.

It’s useful for segregating block-scoped variables that are declared with let or const or class declarations or function declarations that are declared in strict mode,

However, we should add blocks unnecessarily. For instance, the following is useless:

{
  function foo() {}
}

We should never put function declarations in blocks. It’s not allowed in JavaScript since they’re only allowed at the top-level.

What we should do is put function declarations at the top level as follows:

function foo() {}

We should place variables and constants that are declared with let and const in a block, as follows:

{
  let x = 1;
  const y = 2;
}

In the code above, we put x and y in blocks. This way, they can only be accessed inside a block.

No Magic Numbers

Magic numbers are numbers that occur multiple times in our code without any explicit meaning. They should be named constants to make them clear what they mean and that we can reference the constant in multiple places.

This way, we only have to change the value once if we need to change it instead of making changes in multiple places.

For instance, instead of writing:

let x = 1;
let y = 1;
let z = 1;

We can move the 1’s into one constant as follows:

const numPerson = 1;
let x = numPerson;
let y = numPerson;
let z = numPerson;

This way, we know that 1 is the number of persons, and we can also reuse it in multiple places and only change it in one place if we need to change it.

No Multiple Spaces

Multiple spaces are confusing and they aren’t very clean. For instance instead of writing:

if(foo  === "baz") {}

We should instead write:

if(foo === "baz") {}

However, we can put comments after multiple spaces after the end of the line. For instance, the following:

if(foo === "baz") {}    // check if foo is 'baz'

If it makes comments line up better, then it’s OK for comments to come after multiple spaces after a piece of code.

No Multiline Strings

If we want to write strings with multiple lines before we had template strings, we have to write something like the following:

let x = "foo
         bar";

In the code above, we put 'bar' on a new line with a “ . It’s an undocumented feature of JavaScript and now that we have template strings, we shouldn’t use this.

Instead, we should use template strings as follows:

let x = `foo
bar`;

or we can write:

let x = 'foonbar'

Template strings preserve all whitespaces so we have to be precise with the spaces,

The n character also creates a new line.

Photo by Dan Gold on Unsplash

Don’t Use the new Operator Without Assigning the Returned Object

The new operator is used for creating a new instance of a constructor. Therefore, we should always assign it to something.

Using new without assigning the returned result to anything is dubious because either it achieves nothing, or we’re using it to commit side effects.

Constructors aren’t a good place to commit side effects since most people expect it to return an instance of the constructor.

Therefore, we shouldn’t use the new operator without assigning the returned value to the variable or constant of our choice.

For instance, instead of writing:

new  Foo();

We should write:

const foo = new Foo();

Don’t use the Function Constructor

The Function constructor is bad. We pass in strings for specifying the parameters and the function body. The last argument is the body while the arguments before it are the parameters.

They’re hard to debug since they’re all strings. Because they’re all strings, they’re also hard to read.

In addition, if they’re dynamic, then attackers can inject their own code and create their own functions and run malicious code.

Therefore, we should avoid using the Function constructor at all costs. Instead of writing:

const add = new Function("a", "b", "return a + b");

We should write:

const add = (a, b) => a + b;

This way, they’re clean and easy to debug.

Conclusion

Useless blocks, extra spaces, multiline strings that aren’t standard should all be avoided.

Magic numbers should be assigned as constants so they can be understood and reused.

Anything returned with new should be assigned to a variable or constant.

Also, we should never use the Function constructor to make our code easy to read and debug and let us avoid potential security issues.

Categories
JavaScript Mistakes

JavaScript Mistakes — Things We Shouldn’t Put into Our Code

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at things that we shouldn’t be putting in our code.

We Shouldn’t Put Assignment Operators in Conditional Statements

We shouldn’t put assignment operators in conditional assignments. For example, the following is probably a mistake:

if (title = "manager") {

}

The code above sets the title to 'manager' instead of checking if title has the value 'manager' . It’s probably a mistake since most people want to check the value with the === operator rather than doing an assignment operation in the if statement.

What we actually want is:

if (title === "manager") {

}

We Shouldn’t Leave Console in Production Code

console.log and other console methods are very useful for debugging our code. However, before we put them into production, we should have them removed so we aren’t exposing anything to the user unintentionally.

Therefore, the following code shouldn’t be in production code:

console.log("hello.");
console.warn("warning.");
console.error("error.");

Other console method calls also shouldn’t be committed. The only exception to this is when we use console to output data to the user in Node.js apps.

Then we may want to ignore this rule.

We Shouldn’t Put Constant Expressions in Conditions

Constant expressions are most likely a mistake unless we’re doing it intentionally. For instance:

if (false) {
    foo();
}

The code above never runs since the condition inside is always false .

Also, when constant conditions are used in loops, we may get infinite loops or loops that never run. For example, the following is an infinite loop:

while (true) {
    foo();
}

We probably don’t want that in most cases. If the condition in ternary expressions is constant, then it’s pretty useless since it always returns one value.

For instance:

let result = true ? 'foo' : 'bar';

Then result is always 'foo' since the condition is true , so the first value will always be returned.

Examples of code that make more sense include:

while (true) {
  foo();
  if (conditionFalse()){
    break;
  }
}

Putting Control Characters in JavaScript Regular Expressions

Control characters are in ASCII range 0 to 31. They’re special, invisible characters. These characters are rarely used in JavaScript strings so it’s probably a mistake.

For instance, the following is probably not what we want:

`const pattern1 =` /\x00/;
`const pattern2 = new RegExp("\x00");`

It’s very rare that we want to match the null character, which is character 0 in ASCII.

We Shouldn’t Put debugger Statements in Production Code

As its name suggests, debugger is used for debugging. It pauses the program in that line so that we can inspect the items in the current point in the code.

Also, there’re better ways to debug code that with debugger . Production code definitely shouldn’t have debugger in it because it pauses the program that the user is using if it’s present.

For instance, the following is a mistake:

const isTrue = (x) => {
  debugger;
  return x === true;
}

In production code, we should write:

const isTrue = (x) => {
  return x === true;
}

Photo by Sebastian Herrmann on Unsplash

We Should Never have Duplicate Arguments in Functions

Having the multiple parameters with the same means that the last occurrence of the parameter taking on the value of the last parameter with the same name.

For example, if we have:

const foo = (a, b, a) => {
  console.log(a);
}

Then when we call foo as follows:

foo(1, 2, 3);

We see the value 3 logged. This causes confusion and it’s probably a mistake. It doesn’t make much sense to have 2 parameters with the same name.

Instead, we should rename the 3rd parameter:

const foo = (a, b, c) => {
  console.log(a);
}

or remove the second a :

const foo = (a, b) => {
  console.log(a);
}

Conclusion

There’re many kinds of mistakes that can be made when writing JavaScript code because of its forgiving nature. We should never leave debugging code like console or debugger . The only exception is when we use console to output values to users in Node apps.

Constant expressions in conditions are most likely to be mistaken. In conditional statements, we write code that always runs or never runs.

If they’re in loops, then they either create an infinite loop or one that never runs.

In ternary expressions, we create one that always assigns the same value. Therefore, it’s most likely not very useful and it’s a mistake.

Finally, we shouldn’t have duplicate parameter names in functions. It causes confusion since the last value that’s passed in overwrites the first one that’s assigned to the same parameter name.

Categories
JavaScript Mistakes

JavaScript Mistakes — Useless Code and Invalid Regex

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at some useless code that we don’t need to put into our JavaScript code.

No Extra Parentheses

We don’t need parentheses around expressions like arithmetic expressions unless we want to group things that have lower precedence together.

Therefore, we don’t need parentheses on expressions like:

(a * b);

or:

(a * b) + c;

Also, we don’t need parentheses around things like loop variables:

for (let a of (b)){
 //,,,
}

We can remove the parentheses around the b in the loop.

Some operator expressions also don’t need brackets like:

typeof (foo);

We don’t need to wrap parentheses around foo .

Below is another example that has extra parentheses:

(function(){} ? foo() : bar());

We can remove parentheses at the beginning and the end of the line.

If we choose to do an assignment inside a conditional, then we should put parentheses around them to make it clear which variable we’re assigning values to:

while ((foo = bar())) {}

The exception would be a normal for loop, which we write without parentheses:

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

Like with the assignment within loops, we should also put parentheses around assignment expressions in return statements for clarity:

const foo =(b) => {
  return (b = 1);
}

Remove Extra Semicolons

JavaScript lets us put as many semicolons at the end of the line as we want. It does the same thing as a single semicolon, so the extra semicolons are useless.

We also don’t need semicolons after function declarations.

For instance, we shouldn’t have multiple semicolons in the following line:

let x = 1;;;

Instead, we should write:

let x = 1;

An example of a function declaration is the following code:

function foo() {

};

We don’t need an extra semicolon in the code above. Instead, we should write:

function foo() {

}

Reassigning Function Declarations to a Different Value

Since JavaScript functions are just regular variables, they can also be reassigned to anything.

It’s often an indication of a mistake since we would probably want to call the function rather than assigning it to something else.

For example, we don’t want to write:

function fn() {}
fn = foo;

Instead, we should create a variable explicitly and assign a function to the variable to make it clear that it’s actually a variable that we want to reassign values to:

const fn = `function() {}
fn = foo;`

Photo by Christopher Carson on Unsplash

Assigning Members Imported from Modules to Another Value

Since imported members of JavaScript modules are read-only, we can’t assign them to a new value. Therefore, we should have code like:

import { x, y } from "./foo";
x = 1;

We’ll get the error that x is read-only.

This also applies to the importing of default exports.

For instance:

import x from "./foo";
x = 1;

also give the same error.

The following doesn’t give an error with some build tools:

import * as foo from "./foo";
foo.x = 1;

Function Declarations in Nested Blocks

Before ES6, function declarations in nested blocks are supposed to be in the top level of a program or a body of another function.

However, some JavaScript interpreters let function declarations be added to nested blocks.

For example:

function foo() {
  if (true) {
    function bar() {}
  }
};

isn’t supposed to be valid JavaScript because we have the bar function declaration in the if block of the foo function.

To make our code syntactically correct, we should remove the bar function declaration from the if block. We can also use function expressions within our code blocks if we do want to define a function inside.

Invalid Regular Expressions in RegExp Constructors

We don’t want invalid regular expressions in RegExp constructors. The constructor takes any string and tries to return a regular expression object out of it.

Invalid regular expression definitions include things like:

RegExp(']')
RegExp('-', 'z')

We should make sure we pass in a valid regex string or use regex literals instead.

Conclusion

There’re lots of things that JavaScript interpreters allow, but they’re either useless or causes errors. For example, useless parentheses and semicolons should be removed. Function declarations also shouldn’t be reassigned to new values.

Function declarations also aren’t allowed in blocks, even though JavaScript interpreters may still run it.

Finally, invalid regex strings shouldn’t be passed into the RegExp constructor.