Categories
JavaScript

Good Parts of JavaScript — Array Methods and Nested Arrays

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at ways to manipulate JavaScript arrays with methods and nested arrays.

Array and Object Confusion

It may be easy to confuse arrays and objects.

Objects may have numerical keys and the length property.

However, they aren’t arrays.

The typeof operator doesn’t help with checking arrays. This is because using typeof on an array will just return 'object' .

To check if something is an array, we can use the Array.isArray method.

Methods

JavaScript arrays have lots of methods.

There’re methods to map items in an array to different values.

Also, we can combine them in different ways.

There are also a few methods that help to search for items.

For instance, we can use the map method to map the items of an array to different values as follows:

const arr = [1, 2, 3];
const mapped = arr.map(x => x ** 3);

Now we return a new array with entries of arr that are cubed.

So we get [1, 8, 27] as the value of arr .

To combine all entries of an array in some way, we can use the reduce or reduceRight methods.

For instance, we can write:

const arr = [1, 2, 3];
const sum = arr.reduce((acc, entry) => acc + entry, 0);

The code above combines the items in arr by adding them together. The intermediate result is assigned to ac and entry is the array entry being incorporated.

0 is the initial value of the combined result.

reduce combines entries from left to right.

To combine values from right to left, we can write:

const arr = [1, 2, 3];
const sum = arr.reduceRight((acc, entry) => acc + entry, 0);

reduceRight starts from the end of arr to the start. So acc starts with 3, then 2 is added to 3 to get 5, 5 is added to 1 to get 6.

The find and findIndex methods get the first instance of an object.

find returns the first instance of something that matches the criteria that we get.

findIndex returns the index of the first instance of something that’s been found.

So we can write:

const arr = [1, 2, 3];
const result = arr.find(x => x === 1);

and result is 1.

or we can use findIndex :

const arr = [1, 2, 3];
const result = arr.findIndex(x => x === 1);

and get that result is 0, which is the index of 1.

The filter method returns an array that has the entries that meet a given condition.

For instance, we can write:

const arr = [1, 2, 3];
const result = arr.filter(x => x % 2 === 1);

Then result is [1, 3] since we specified x % 2 === 1 . The condition that we specified is to return all the odd numbers.

Dimensions

There’re no multidimensional arrays in JavaScript.

However, we can have arrays of arrays.

For instance, we can create an array of arrays by writing:

const arr = [];
arr[0] = [1, 2, 3];
arr[1] = [4, 5, 6];

Now we can loop through them by writing:

const arr = [];
arr[0] = [1, 2, 3];
arr[1] = [4, 5, 6];

for (let i = 0; i < arr.length; i++) {
  for (let j = 0; j < arr[i].length; j++) {
    console.log(arr[i][j]);
  }
}

We looped through the items in the top-level array.

Then in the loop body, we loop through the item of each array.

If we run the loop, we get:

1
2
3
4
5
6

from the console log.

Also, we can use the for-of loop to make this clearer. For instance, we can write:

const arr = [];
arr[0] = [1, 2, 3];
arr[1] = [4, 5, 6];

for (const a of arr) {
  for (const b of a) {
    console.log(b);
  }
}

And we get the same result. We just used the for-of loop to make our iteration code cleaner.

Conclusion

Array methods will make our lives easier. We can call the find and findIndex methods to find items.

map will map array entries from one value to another.

reduce and reduceRight let us combine array entries to a single value.

We can create JavaScript nested arrays and use them as multidimensional arrays.

Categories
JavaScript

Good Parts of JavaScript — Objects Types and Structure

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at some good parts of JavaScript objects, including looking at the type and structure.

Getting Types of Property Values

We can use the typeof operator to get the value of a property.

For instance, given the following object:

const obj = {  
  'foo': 1,  
  'bar': {  
    'baz': 2  
  }  
}

We can write the following by writing:

typeof obj.foo

Then we should get 'number' .

However, we want to be careful with this operator because properties up the prototype chain can also return a value.

For instance, we can write:

typeof obj.toString

and we’ll see 'function' returned.

Therefore, if we don’t want to get the types of an object’s prototypes by accident, we should use the hasOwnProperty method to check if the property is in the object first.

For instance, we can write:

obj.hasOwnProperty('foo')

to check if 'foo' is a property of obj itself.

Then that returns true since it’s defined in obj itself.

On the other hand, if we write:

obj.hasOwnProperty('toString')

Then we should get false returned since it’s part of obj ‘s prototype.

Enumeration

There’re a few ways to enumerate object properties in JavaScript.

We can use the for-in loop to loop through an object’s properties.

However, there are 2 catches. The order of the enumeration isn’t guaranteed. Also, for-in loops through all the properties of all of an object’s prototype up the prototype chain.

For instance, we can write:

for (const key in obj) {  
  //..  
}

to loop through the keys of obj and its prototypes keys.

To prevent us from looping through an object’s prototypes’ properties, we can use the hasOwnProperty method again to check if the property is an own property or not.

For instance, we can write:

for (const key in obj) {  
  if (obj.hasOwnProperty(key)) {  
    //..  
  }  
}

Object.keys

If we only want to loop through an object’s own keys, we can use the Object.keys method to get them.

It returns an array of keys to the own enumerable properties of an object.

Only string keys are returned.

For instance, we can write:

for (const key of Object.keys(obj)) {  
  //...  
}

We use the for-of instead of the for-in loop to loop through the own keys of obj .

Reflect.ownKeys

Reflect.ownKeys does is very similar to Object.keys . It returns an array of own keys of the given object.

The difference is that both string and symbols keys are returned.

For instance, we can write:

for (const key of `Reflect.ownKeys`(obj)) {  
  //...  
}

Delete

The delete operator is used to removing a property from an object.

If an object has the given property, then it’ll be removed if we use the delete operator.

For instance, given the following object:

const obj = {  
  'foo': 1,  
  'bar': {  
    'baz': 2  
  }  
}

We can use:

delete obj.foo;

to remove the foo property from obj .

Global Abatement

One bad part of JavaScript is that it’s too easy to define global variables.

This makes our program less robust with namespace collisions and makes errors hard to trace.

We can minimize the use of global variables in a few ways.

We can out our local code in objects. We can put them in blocks, or we can put them in modules.

If we create an object:

const obj = {  
  'foo': 1,  
  'bar': {  
    'baz': 2  
  }  
}

Then obj.foo isn’t a global object.

We should also never attach anything like a property of window or global in Node apps.

Also, if we put them in blocks, then we can use let and const to declare block-scoped variables and constants.

They won’t be available globally.

Items in modules also aren’t available globally.

Conclusion

We can get the types of property values by using the typeof operator.

Enumeration can be done with the for-in, for-of, Object.keys or Reflect.ownKeys methods.

The delete operator can be used to remove properties from an object.

To reduce the use of global variables, we can put variables in blocks, modules, or objects.

Categories
JavaScript

Good Parts of JavaScript — Currying, Memoization, and Inheritance

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at ways to curry functions, memoization, and inheritance.

Curry

Curry functions allow us to produce a new function by combining a function and an argument.

We can create a curry function to return a function that has some arguments applied and let us apply the remaining arguments by writing the following:

const curry = (fn, ...args) => {
  return (...moreArgs) => {
    return fn.apply(null, [...args, ...moreArgs]);
  };
}

In the code above, we have the curry function, which takes a function fn and some arguments args after it.

Inside it, we return a function that returns fn with all the arguments from both functions applied to it.

This way, we first apply the arguments in args , then we apply the arguments in moreArgs to fn .

Now if we call it as follows:

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

const curried = curry(add, 1);
const result = curried(2, 3);

We first get a function with 1 applied to add in curried .

Then we get the final sum by applying 2 and 3 to curried .

Therefore, result is 6.

We can improve curry by replacing apply with the spread syntax:

const curry = (fn, ...args) => {
  return (...moreArgs) => {
    return fn(...[...args, ...moreArgs]);
  };
}

This is cleaner and now fn can be arrow functions in addition to a traditional function.

Memoization

We can do memorization by keeping previously computed results that we need later.

For instance, if we have a function that computes a Fibonacci number, we can write:

const fib = (num) => {
  let a = 1,
    b = 1;
  for (let i = 1; i <= num; i++) {
    [a, b] = [b, a + b];
  }
  return a;
}

In the code above, we store the values of a and b .

We keep the values of a and b so that we can use it to create new Fibonacci numbers with them.

Inheritance

JavaScript inheritance is done by using prototypical inheritance.

However, it has a syntax that resembles classical inheritance with the class syntax.

For instance, we can implement inheritance by writing the following code:

class Animal {
  speak() {
    //...
  }
}

class Dog extends Animal {}
class Cat extends Animal {}

In the code above, we used the class keyword to create constructors.

The extends keyword is used to inherit members from Animal in the Dog and Cat constructors.

Now if we create a new Dog instance:

const dog = new Dog();

We have the __proto__ property in Dog which is set to the Animal constructor.

The speak method is in the object that’s set as the value of the __proto__ property.

We can call the speak method by writing dog.speak() .

Prototypal Inheritance

If we have object literals, we can use the Object.create method to inherit items from another object.

We can use it as follows:

const parent = {
  foo() {
    //...
  }
}

const child = Object.create(parent);
console.log(child);

In the code above, we have the parent object with the foo method.

Then we can use the Object.create method to create an object with parent as the prototype.

If we log the child object’s content, we have the __proto__ property which has the prototype of child .

The __proto__ property has the foo method.

Like inherited methods from class/constructor instances, we can call foo as follows:

child.foo();

Conclusion

We can curry functions by returning a function that applies arguments to a function that hasn’t been applied yet.

Memoization can be done by storing values that will be used later so we can use them.

For inheritance, we can create constructors with the class syntax with the extends keyword.

We can also use the Object.create method for creating objects with our own prototypes.

This is a convenient way to create objects from a prototype object and inherit its properties.

Categories
JavaScript

Good Parts of JavaScript — Objects

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at some good parts of JavaScript objects.

JavaScript Objects

In JavaScript, the primitive types are their own types, and objects are object types.

Primitive types are numbers, booleans, strings, null , undefined , symbols and bigint.

Everything else is objects.

Objects in JavaScript are mutable kets collections. Also, arrays are objects.

Regular expressions are also objects. And objects are objects.

An object is a container of properties. Properties have names and values.

A property can be a string, including the empty string. A value can be any JavaScript value except for undefined .

There are no true classes in JavaScript. There are no constraints on how property keys and values are structured.

Objects can contain other objects, so we can use them to represent tree structures.

We can implement inheritance with prototypes.

A prototype is a template object that other objects can inherit properties from.

Object Literals

Object literals are a way convenient way for us to define objects.

We create one by adding curly braces and then add key-value pairs inside it.

Property keys can be strings and values can be anything.

We can use any string as property names, including an empty string.

If our name is a valid identifier name and it’s not a reserved word, then we don’t need quotes.

For instance, we can create an object literal by writing:

const obj = {
  'foo': 1,
  'bar': false
}

or we can write:

const obj = {
  foo: 1,
  bar: false
}

since foo and bar are valid identifier names.

Objects can be nested, we can write:

const obj = {
  'foo': 1,
  'bar': {
    'baz': 2
  }
}

Retrieval

We can get a property’s value either with the dot notation or the bracket notation.

The . notation is better because it’s shorter and easier to read.

For instance, we can write:

obj.foo

and get 1.

And we can write:

obj.bar.baz

to get 2.

The bracket notation is mainly used for accessing properties dynamically and also for getting properties that are invalid identifiers.

For instance, we can write:

obj["first-name"]

to get the 'first-name' property of obj .

If we try to get a property from something that’s undefined , then we’ll get a TypeError exception.

The prevent that from happening, we need to use the && operator as follows:

obj.bar && obj.bar.baz

Now obj.bar.baz is run only with obj.bar is defined.

Update

We can update object property values by using the assignment operator.

For instance, we can write:

obj['foo'] = 3;

or write:

obj.foo = 3;

Reference

Objects are always passed by reference. Therefore, if we modify an object’s property value as follows:

const obj = {
  'foo': 1,
  'bar': {
    'baz': 2
  }
}

const obj2 = obj;
obj.foo = 3;

Both obj.foo and obj2.foo are 3 instead of 1.

Prototype

Almost every object is linked to a prototype object from which inherit properties.

All objects by default are linked to Object.prototype .

The only exception is when we create an object as follows:

const obj = Object.create(null);

The argument for Object.create is the prototype of the object returned by Object.create.

Therefore, obj will have no prototype.

Otherwise, our object will have a prototype. For instance, if we create an empty object:

const obj = {};

We’ll see that the __proto__ property will have the properties of Object.prototype .

If we update a property, it’ll update the property on the object itself rather than its prototype.

The prototype link is only used for retrieval. If we get a value from an object and if it’s not in the object itself.

Then the JavaScript interpreter will get the value from the prototype.

If a property isn’t in the object itself or its prototypes, then undefined is returned.

This is called delegation.

Conclusion

JavaScript objects can be created with object literals.

Most objects have prototypes except for ones that are explicitly created without a prototype.

A prototype is an object where properties can be inherited from another object.

Categories
JavaScript

Good Parts of JavaScript — Arrays

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at ways to define and use arrays.

Array Literals

Array literals are the easiest way to define arrays.

We can create one by writing:

const arr = ['foo', 'bar', 'baz'];

Then we can access the content its index:

arr[1]

That’ll return 'bar' since the index of the first entry is 0.

Arrays also has the length property to check the size of an array.

We can write:

arr.length

to get the length of arr , which would be 3.

Object literals with numeric keys are similar to arrays, but we can’t iterate through an object that has numeric keys and the length property.

JavaScript array entries don’t have to be the same type, so we can write:

const arr = ['foo', 1, 'baz'];

And that is a valid array.

Length

Arrays have the length property. JavaScript arrays don’t use length as an upper bound.

We can access any index of an array as long as it’s a non-negative integer.

However, if the array index isn’t associated with any entry, then we get undefined .

We can set the length property explicitly.

Making the length larger doesn’t allocate more space for the array.

However, making the length smaller will cause properties with an index greater than or equal to the next length will be deleted.

Because we can access any index, we can add a new element to an array by writing:

arr[arr.length] = 'baz';

2 other convenient ways to add items to the end of the array are either to use the push method or the spread operator.

To use the push method, we write:

arr.push('baz');

push adds an entry to arr in place.

To use the spread operator, we can write:

arr = [...arr, 'baz'];

arr is spread into a new array and then we add 'baz' to the end of it and then assign it back to arr .

Delete

Since JavaScript arrays are objects, we can use the delete operator to remove an element with the given index.

For instance, we can write:

delete arr[2];

to remove 'baz' from the arr given that arr is:

const arr = ['foo', 1, 'baz'];

However, that will leave a hole in the array.

What we want to do usually to remove the item along with the slot.

We can make this easy by using the splice method.

To remove an array item with the splice method we can write:

arr.splice(1, 1);

The code above will remove one entry from starting from index 1.

Therefore, the only item with index 1 is removed.

splice removed the item in place, so that we remove the item from arr without leaving an empty slot.

Enumeration

We can use the for-in loop to loop through array entries since we can loop through the array indexes as we do with keys.

However, since the order isn’t guaranteed, we can’t use this to loop through the items reliably.

Also, for-in loops through the items in the array’s prototype, which we probably don’t want.

Therefore, it’s not good for looping through arrays.

Instead, we can use the for loop or for-of loop to loop through the items.

For instance, we can write:

for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

We initialize i to the starring index and we loop through the array’s length minus 1.

To use the for-of loop, we write:

for (const a of arr) {
  console.log(arr);
}

They’re both very convenient choices.

Conclusion

We can create arrays and loop through them easily.

The most convenient way to create an array is to use the array literal notation.

JavaScript array can have any kind of content in it.

To add items to an array, we can use the push method or the spread operator.

To remove an item, we can use the splice method.

To loop through arrays, we can use the for loop or the for-of loop.

They’re both better than the for-in loop for looping through arrays.