Categories
JavaScript Tips

Useful JavaScript Tips — Arrays, and Variables

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some tips we should follow to write JavaScript code faster and better.

Assignment Operators

We can save some typing by using some compound assignment operators.

We can use the ++ and -- operators to increment and decrement by one respectively.

For instance, we can write:

a++

to increment a by 1.

Likewise, we can use:

++a

to do the same thing.

The only difference is whether it returns the later value or the old one.

We can do the same thing with -- , but decrements the value instead.

Ternary Operator

If we have:

const newValue;
if(value > 100) {
  newValue = 5;
} else {
  newValue = 2;
}

Then we can shorten it by writing:

const newValue = (`value > 100) ? 5 : 2;`

They do the same thing.

Null, Undefined, or Empty Checks

We can check for null , undefined and an empty string together by writing the following:

if (foo !== null || foo !== undefined || foo !== '') {
  const bar = foo;
}

We have to check null , undefined and empty string individually.

This is because empty string, null and undefined are different.

If we want to check other falsy values like 0 or NaN , then we can shorten it to:

const bar = foo || 'default';

Then when foo is any falsy value, then 'default' will be assigned to bar .

Array Literals

Instead of using the Array constructor:

const a = new Array();
a[0] = 'foo';
a[1] = 'bar';

We can write an array literal as follows:

const a = ['foo', 'bar'];

They do the same thing, but the array literal notation is much shorter.

Associative Array

We shouldn’t use the Array constructor for creating associative arrays.

Rather, we should create an object with dynamic keys.

For instance, we can write:

const skills = {
  'markup language' : 'HTML5',
  'programming language' : 'JavaScript'
};

We have 2 keys which aren’t valid identifiers.

But we can still use them since JavaScript objects can take string property names.

Asynchronous Loops

If we want to loop through setTimeout calls, then we can use let as follows:

for (let i = 0; i < 10; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}

let is block-scoped, so the current value of i would be passed in.

Create an Array Sequence

We can create an array with a sequence of numbers starting from 0 with the Array constructor, fill , and map .

For instance, we can write:

const arr = Array(50).fill().map((_, i) => i);

We used the Array constructor to create an array with empty slots.

Then we called fill to fill the empty array with undefined .

This way, we can use map to map the entries by passing in a callback and return the index i of each entry.

Then we get an array between 0 and 50.

Ordering Object Properties

We can use the Object.keys method to return properties in an array.

Arrays are sortable so we can use that.

For instance, we can write:

Object.keys(obj)

and get the keys.

Also, we can use the Map constructor to create a map, which is traversed in insertion order.

For instance, we can write:

const map = new Map();
map.set('foo', 1);
map.set('@', 2);
map.set('bar', 3);
for (const [key, value] of map) {
  console.log(key, value);
}

Now we have Map instance that we can loop through keys in the same order that they’re inserted.

Avoiding Using Arguments

Don’t use the arguments object to get all the arguments.

Instead, we use the rest operator to get function arguments as an array.

For instance, we can write:

const foo = (...args) => {
  `for(const a of args) {
    //...
  }
}`

The ... is the rest operator which collects all the arguments in a function call and returns it as an array.

We can then call it by writing:

foo(1, 2, 3);

and args would be [1, 2, 3] .

Conclusion

We can use the rest operator to get the arguments from a function call.

The assignment operators are great. We can use the ++ and -- operators to increment and decrement our variables.

Also, we should use array literals as much as we can.

Categories
JavaScript Tips

Useful JavaScript Tips — Arrays and JSON

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some tips we should follow to write JavaScript code faster and better.

Calculating the Average and Median

We can get the average by calculating the sum of the array and dividing that by the length of the array.

For instance, we can write:

const values = [2, 10, 28];
const sum = values.reduce((total, current) => current + total, 0);
const avg = sum / values.length;

We have the values array, which we get the sum of by using reduce .

Then we divide the returned sum by the length of values .

To get the median, we can sort the array, then get the average of the low and high middle value from the sorted array.

For instance, we can write:

const values = [2, 10, 28];
values.sort((a, b) => a - b);
const lowMiddle = Math.floor((values.length - 1) / 2);
const highMiddle = Math.ceil((values.length - 1) / 2);
const median = (values[lowMiddle] + values[highMiddle]) / 2;

We call sort to sort the array in ascending order by using the (a, b) => a — b callback.

Then we get the index of the low middle value by getting the floor of value ‘s length minus 1 divided by 2.

Likewise, we get the index of the high middle value by getting the ceiling of that.

Then we get the average of both values entries to get the median .

JSON.Stringify

We can turn objects into a string with JSON.stringify .

For instance, we can write:

const obj = {
  foo: `1`,
  bar: 2
};

const selectedProperties = ['foo'];

const str = JSON.stringify(obj, selectedProperties);

We have the obj object which we called stringify on with obj and select the properties with the second argument.

Then we get:

"{"foo":1}"

as the value of str .

We can also pass in a function:

const obj = {
  foo: 1,
  bar: 2
};

const selectedProperties = (key, val) => {
  if (!key || key === 'foo') {
    return val;
  }

  return;
}

const str = JSON.stringify(obj, selectedProperties);

We have a function that checks when to return val according to the given property.

Object.defineProperties

We can use Object.defineProperty to define a property to get more control over it.

For instance, we can write:

Object.defineProperty(obj, 'prop', {
  value: '123',
  enumerable: false,
  writable: false,
  configurable: false
});

We defined the prop property in obj value '123' , and all other properties set to false .

enumerable means whether we can see it from Object.keys or the for-in loop.

writable means whether we can change the value of it.

configurable means whether we can change the property descriptors.

Flattening Multidimensional Arrays

We can use the flat method to flatten multidimensional arrays.

For instance, we can write:

const arr = [[1, 2],[3, 4, 5]];
const flattened = arr.flat();

Then we get [1, 2, 3, 4, 5] for flattened .

We can also use concat to concatenate arrays.

For instance, we can write:

`const flattened` = [].concat.apply([], `arr`);

Also, we can use reduce to do the same thing:

const flattened = arr.reduce((flattened, curr) => flattened.concat(curr));

The spread operator can also do the same thing:

const arr = [[1, 2],[3, 4, 5]];
const flattened = arr.reduce((flattened, curr) => [...flattened, ...curr]);

That returns the arrays merged together.

We can also use the concat method with the spread operator:

const arr = [[1, 2],[3, 4, 5]];
const flattened = [].concat(...arr);

We spread the arr entries into arguments of the concat method.

Then concat appends the entries from the arrays.

Deduplicating an Array

We can remove duplicates from an array in several ways.

We can use the filter method to only return an array with the first instances of each entry by writing:

const deduped = [1, 1, 'b', 'b'].filter((el, i, arr) => arr.indexOf(el) === i);

We use the indexOf method, which returns the index of the first instance of entry to check whether it’s the first instance.

Also, we can convert it to a set to remove the duplicates and put spread it back into an array:

const deduped = Array.from(new Set([1, 1, 'b', 'b']));

or:

const deduped = [...new Set([1, 1, 'b', 'b'])];

Converting an array to a set removes the duplicates. Then we use Array.from or the spread operator to turn it back to a set.

Conclusion

We can use built-in methods and operations to calculate averages and medians.

Also, we can use them to remove duplicates.

We can also use them to flatten arrays.

JSON.stringify can take arguments to select which properties to stringify.

Categories
JavaScript Tips

JavaScript Tips — Good Constructs to Use

JavaScript is a very flexible language. There’s a lot of things in JavaScript that we probably shouldn’t write. Old constructs that aren’t good coexist with new constructures that are better.

In this article, we’ll look at some good parts of JavaScript that we should use regularly.

Don’t Use var, Use let or const

var is an outdated keyword for declaring variables. Instead, we should use let and const . let and const are both block-scoped, so that we can use them without worrying about clashing scopes as long as they’re in a block.

For instance, we can write the following:

let x = 1;
const y = 2;

instead of:

var x = 1;
var y = 2;

const also have the advantage that we can’t reassign a new value to it. However, it doesn’t make an object immutable.

Use === or Object.is Instead of ==

== saves one character of typing, but the rules for comparing with == is complex and hard to remember. It also produces lots of unexpected results. Therefore, we shouldn’t use == .

For instance, the following both return true :

[10]  == 10
'10' == 10

We probably don’t want that. Therefore, we should write the following instead:

[10] === 10
'10' === 10

Then they both return false since the data type and value of both operands have to match in order for the === to consider them the same. However, NaN === NaN returns false .

To check for NaN , we should use the isNaN function, which tries to convert its argument to a number and check against that. Therefore, isNaN(‘NaN’) and isNaN(NaN) both return true .

There’s also the Number.isNaN function, which doesn’t do any conversion when checking. Therefore, Number.isNaN(‘NaN’) returns false and Number.isNaN(NaN) returns true .

There’s also the Object.is method, which does the same thing as === ecept that NaN is the same as itself.

We can use that as follows:

Object.is('foo', 'bar')

The arguments are the 2 things that we want to compare.

undefined, null, 0, false, NaN, ‘’ (empty string) are all Falsy.

We have to remember these since they all return false when we try to convert them to boolean with !! or Boolean .

Use Semicolons for Line Termination

JavaScript is forgiving in that it doesn’t need semicolons for terminating lines. It’ll just insert the semicolons after line breaks or wherever it thinks it can end the line.

However, this will produce unexpected results. For instance:

const foo = () => {
  return
  {
    first: 'john'
  };
}

will return undefined because the semicolon is added after return , so the code below it is never run.

Therefore, we should insert semicolons as needed to clarify where a line ends.

Use Class Syntax for Object Constructors

In JavaScript, classes are the same as object constructore functions. However, the syntax is stricter so that it’s harder to make mistakes, especially when we need to do inheritance. For instance, we can write the following class:

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
}

which is the same as:

function Person(firstName, lastName){
  this.firstName =  firstName;
  this.lastName = lastName;
}

It’s just that the class syntax is more conventional syntax, especially for people who worked with other object-oriented languages.

It makes even more sense if we have methods. For instance, with the class syntax, we write:

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  fullName() {
    return `${this.firstName } ${this.lastName }`;
  }
}

The Person class above has the fullName method. On the other hand, with the old constructor function syntax, we write:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

Person.prototype.fullName = function() {
  return `${this.firstName } ${this.lastName }`;
}

This just doesn’t make as much sense for many developers, especially for non-JavaScript developers.

The class syntax makes things much clearer. The class syntax makes even more sense with inheritance. With the old syntax, we write:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

Person.prototype.fullName = function() {
  return `${this.firstName } ${this.lastName }`;
}

function Student(studentId) {
  Person.call(this, studentId);
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Person;

There’re no errors if we missed anything when we write the code above.

However, with the class syntax, we write:

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  fullName() {
    return `${this.firstName } ${this.lastName }`;
  }
}

class Student extends Person {
  constructor(firstName, lastName, studentId) {
    super(firstName, lastName);
    this.studentId = studentId;
  }
}

We’ll also get errors if we didn’t follow the syntax like forgetting to call super when we have extends .

Conclusion

There’re a few important things we should use to write JavaScript code, including === instead of == , class syntax instead of constructor functions and prototype, use let and const instead of var to declare variables and constants, and remember falsy values

Categories
JavaScript Tips

Node.js Tips — Scheduled Tasks, Jest Tests, and Headers for Tests

Like any kind of apps, there are difficult issues to solve when we write Node apps.

In this article, we’ll look at some solutions to common problems when writing Node apps.

Looping Through Dynamic Test Cases with Jest

We can use the tests.each method to loop through each tets.

For instance, we can write:

test.each([[4, 5, 9], [1, 2, 3], [2, 3, 5]])(
  'add(%i, %i)',
  (a, b, expected) => {
    expect(a + b).toBe(expected);
  },
);

The first argument is the items we want to pass into each test.

The nested array entries are the parameters for the callback.

The 2nd argument is the name of each test.

The 3rd is a callback to let the arguments and run our expectations.

Setting Default Headers with Supertest

We can create a header we can use with our test.

Then we can pass it into the set method.

For instance, we can write:

const request = require("supertest");

const baseUrl = 'http://localhost';
request = request(baseUrl);
const commonHeaders = { authorization: "abc" };

describe("testing", () => {
  it.should('present authorization header to server', (done) => {
    request.get('/foo')
      .set(commonHeaders)
      .set({ foo: "bar" })
      .expect(200, done)
  })

})

commonHeaders has the shared headers between multiple tests.

We just pass that into the set method.

Then we can pass other headers into the set method that are specific to the test.

Read a File Synchronously in Node.js

To read a file synchronously with Node, we can use the readFileSync method.

For instance, we can write:

const fs = require('fs');
const content = fs.readFileSync('file');
console.log(content);

We just pass in the path to the file and the content will be returned.

Base64 Encode a JavaScript Object

We can base64 encode a JavaScript object by converting it to a string with JSON.stringigy .

Then we can call Buffer.from to convert it to a buffer and then call toString to convert it to a base64 string.

For instance, we can write:

const str = JSON.stringify(obj);
const objJsonB64 = Buffer.from(str).toString("base64");

Buffer.from converts the stringified JSON object to a byte stream.

Then we call toString with the 'base64' argument to convert it to a base64 string.

Mongoose Populate Embedded

We can call populate on embedded documents with Mongoose if we define a schema with the related schemas.

For instance, if we have:

const UserSchema = new Schema({
  name: String,
  friends: [{ type: ObjectId, ref: 'User' }]
});

Then we have a self-referencing schema since friends is referencing another User document.

Now we can call populate with friends by writing:

User.
  findOne({ name: 'james' }).
  populate({
    path: 'friends',
    populate: { path: 'friends' }
  });

We call populate the friends to get friends.

And we can use the populate property to get friends of friends.

Running a Function Everyday

We can run a function in a scheduled manner by using the node-schedule package.

For instance, we can write:

import schedule from 'node-schedule'

schedule.scheduleJob('0 0 0 * * *', () => {
  //...
})

We run the schedule.scheduleJob to run the callback with the scheduled specified by the string.

It takes a string in that specifies the schedule in the same way as a cron job.

The first number is the second.

The 2nd is the minute.

The 3rd is the hour.

The 4th is the day of the month.

The 5th is the month.

The 6th is the day of the week.

We specify the hour, minute, and second to specify when it’ll run in the day.

Then the rest are asterisks to that it’ll run every day.

We can also specify the date instead of a cron format string.

For instance, we can write:

const schedule = require('node-schedule');
const date = new Date(2020, 0, 0, 0, 0, 0);

const j = schedule.scheduleJob(date, () => {
  console.log('hello');
});

Then the callback only runs on the given date.

We can also set recurrence rules.

For instance, we can write:

const schedule = require('node-schedule');

const rule = new schedule.RecurrenceRule();
rule.minute = 30;

const j = schedule.scheduleJob(rule, () => {
  console.log('half hour job');
});

We use the schedule.RecurrenceRule constructor to create a rule.

We set the minute in the example above.

But we can also set the second , hour , date , month , year , and dayOfWeek .

Conclusion

node-schedule is a useful scheduler package.

We can set headers for tests with supertest.

Jest can define and run tests dynamically.

MongoDB can reference related documents.

We can convert JavaScript objects into base64 strings.

Categories
JavaScript Tips

JavaScript Tips — Jest Mocks, React Background, and More

Like any kind of apps, there are difficult issues to solve when we write JavaScript apps.

In this article, we’ll look at some solutions to common JavaScript problems.

Regex to Check Whether a String Contains Only Numbers

We can use a regex to check if a string has only numbers.

For instance, we can write:

const reg = /^d+$/;

^ matches the string from the beginning, and d is the digit.

Javascript Filename Naming Convention

JavaScript filename should follow some common conventions.

We should use all lowercase filenames.

Also, we don’t want to use spaces in the filename.

We can optionally use a hyphen as a word separator.

And we may also add a version number in our file name if we have one.

By updating the version number in the file name, we always serve the latest one with the CDN alongside the older version.

Calling a Parent Window Function from an iframe

We can access the parent window with the window.parent property.

So if we want to call a function in the parent window from an iframe, we can write:

<a onclick="parent.foo();" href="#" >click me</a>

foo is a top-level function in the parent window.

Center a Popup Window on the Screen

To center a popup window on the screen, we can do some calculations to center the window and pass that off to the specification string.

For instance, we can write:

const openPopup = (url, title, w, h) => {
  const left = (screen.width / 2) - (w / 2);
  const top = (screen.height / 2) - (h / 2);
  return window.open(url, title, `width=${w}, height=${h}, top=${top}, left=${top}`);
}

We get the left coordinate by using the width divided by 2 minus the width divided by 2 to get the x coordinate of the top left corner.

Likewise, we do the same thing but replace the width with the height to get the y coordinate of the top left corner.

Then we pass those to the specification string and also do the same with the width and height.

Setting a Background Image With React Inline Styles

To set a background image with React inline styles, we can import the image as a module.

Then we can interpolate that into the CSS string for setting the background image.

For instance, we can write:

import Background from '../images/background.png';

const styles = {
  backgroundImage: `url(${Background})`
}

We set the backgroundImage property with the url string with the Background image we imported.

Remove Everything After a Given Character

To remove the part of a string after a given character from a string, we can use the split method.

For instance, we can write:

url.split('?')[0]

Then we get part of the url string before the ? .

A Practical Use for a Closure in JavaScript

Closures are great for hiding private things like variables and functions that we don’t want to expose to the outside.

For instance, we can write:

const obj = (() => {
  const private = () => {
    console.log('hello');
  }

  return {
    public() {
      private();
    }
  }
})();

private is a private function.

And public is a function that’s in obj , so it’s available to code outside.

Get the Real Width and Height of an Image

To get the real width and height of an image, we can use the naturalHeight property to get the real height and naturalWidth to get the real width.

For instance, we can write:

const height = document.querySelector('img').naturalHeight;

and:

const width = document.querySelector('img').naturalWidth;

This is available since HTML5.

Mock an ES6 Module Import Using Jest

To mock an ES6 module import using Jest, we can use the jest.fn() function to mock a function.

For instance, we can write:

logger.js

export const log = (y) => console.log(y)

module.js

import { log } from './logger';

export default (x) => {
  doSomething(x * 2);
}

module.test.js

import module from '../module';
import * as `logger` from '../`logger`';

describe('module test', () => {
  it('logs the double the input', () => {
    dependency.`log` = jest.fn();
    module(2);
    expect(dependency.`log`).toBeCalledWith(4);
  });
});

All we have to do is to call jest.fn to create a mock function.

We imported the whole module, so the members aren’t read-only.

Therefore, we can assign our own mock function to it.

Then we call our module function to test our function and check our results.

Conclusion

We should follow some common file naming conventions for naming JavaScript files.

Also, we can mock functions in Jest with the jest.fn() method.

A popup can be centered on the screen.

We can set a background image by importing it and interpolating it in a CSS string in a React component.