Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Object Properties

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at object properties.

Object Properties and Attributes

Object properties have their own attributes.

They include the enumerable and configurable attributes.

And they’re both booleans.

Enumerable means if we can enumerate the properties.

And configurable means the property can’t be deleted or change any attributes if it’s false .

We can use the Object.getOwnPropertyDescriptor method by writing:

let obj = {
  name: 'james'
}
console.log(Object.getOwnPropertyDescriptor(obj, 'name'));

And we get:

{value: "james", writable: true, enumerable: true, configurable: true}

from the console log.

Object Methods

ES6 comes with various object methods.

Copy Properties using Object.assign

We can use the Object.assign method to copy properties.

For instance, we can write:

let a = {}
Object.assign(a, {
  age: 25
})

Then a is:

{age: 25}

We copy the age property to the a object, so that’s what we get.

Object.assign can take multiple source objects.

For instance, we can write:

let a = {}
Object.assign(a, {
  a: 2
}, {
  c: 4
}, {
  b: 5
})

Then a is:

{a: 2, c: 4, b: 5}

All the properties from each object will be copied.

If there’re any conflicts:

let a = {
  a: 1,
  b: 2
}
Object.assign(a, {
  a: 2
}, {
  c: 4
}, {
  b: 5
})

console.log(a)

then the later ones will make precedences.

So a is the same.

Compare Values with Object.is

We can compare values with Object.is .

It’s mostly the same as === , except that NaN is equal to itself.

And +0 is not the same as -0 .

For instance, if we have:

console.log(NaN === NaN)
console.log(-0 === +0)

Then we get:

false
true

And if we have:

console.log(Object.is(NaN, NaN))
console.log(Object.is(-0, +0))

We get:

true
false

Destructuring

Destructuring lets us decompose object properties into variables.

For instance, instead of writing:

const config = {
  server: 'localhost',
  port: '8080'
}
const server = config.server;
const port = config.port;

We can write:

const config = {
  server: 'localhost',
  port: '8080'
}
const {
  server,
  port
} = config

It’s much shorter than the first example.

Destructuring also works on arrays.

For instance, we can write:

const arr = ['a', 'b'];
const [a, b] = arr;

Then a is 'a' and b is 'b' .

It’s also handy for swapping variable values.

For instance, we can write:

let a = 1,
  b = 2;
[b, a] = [a, b];

Then b is 1 and a is 2.

Built-in Objects

JavaScript comes with various constructors.

They include ones like Object , Array , Boolean , Function , Number , and String .

These can create various kinds of objects.

Utility objects includes Math , Date , and RegExp .

Error objects can be created with the Error constructor.

Object

The Object constructor can be used to create objects.

So these are equivalent:

const o = {};
const o = new Object();

The 2nd one is just longer.

They both inherit from the Object.prototype which has various built-in properties.

For instance, there’s the toString method to convert an object to a string.

And there’s the valueOf method to return a representation of an object.

For simple objects, valueOf just returns the object. So:

console.log(o.valueOf() === o)

And we get true .

Conclusion

Objects have various properties and methods.

They inherit various methods that let us convert to different forms.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Loops and Functions

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at various kinds of loops and functions.

Loops

There are various kinds of loops we can use with JavaScript.

For…in Loops

The for…in loop lets us loop through an object’s keys.

For example, we can write:

let obj = {
  a: 1,
  b: 2,
  c: 3
}
for (const key in obj) {
  console.log(key, obj[key])
}

And we get the key with the key and we can access the value with obj[key] .

For…of Loops

The for…of loop lets us iterate through iterable objects, including arrays.

For instance, we can write:

let arr = [1, 2, 3]
for (const a of arr) {
  console.log(a);
}

We have the arr array which we loop through with the for-of loop.

a has the array entry.

Comments

Comments are part of the code that’s ignore by JavaSdcript engines.

We can use them to explain how our code works.

Single line comments starts with // and ends at the end of the line.

Multiline comments starts with /* and ends with */ .

Anything in between them are ignored.

So we can write:

// single line

and:

/* multi-line comment on a single line */

or:

/*
  multi-line comment on a single line
*/

Functions

Functions is a reusable piece of code.

We can use them to do something in our code.

There are various kinds of functions, they include:

  • anonymous functions
  • callbacks
  • immediate (self-invoking) functions
  • inner functions (functions defined inside other functions)
  • functions that return functions
  • functions that redefine themselves
  • closures
  • arrow functions

They let us group together code, give it a name, and reuse it later.

We can define a function by writing:

function sum(a, b) {
  let c = a + b;
  return c;
}

And we return the sum of a and b in the function.

a and b are parameters and we return a value.

We have the function keyword to define a function.

return lets us return a value.

If there’s no return statement, then it returns undefined .

We can also create arrow functions by writing

const sum = (a, b) => {
  let c = a + b;
  return c;
}

or we can write:

const sum = (a, b) => a + b

They don’t bind to this and they’re shorter.

Calling a Function

We can call a function by writing:

const result = sum(1, 2);

The values in the parentheses are the arguments.

They’re set as the value of the parameters.

Parameters

Parameters are the items in the parentheses of the function.

So if we have:

function sum(a, b) {
  let c = a + b;
  return c;
}

then a and b are parentheses.

We pass in arguments to set them.

They’re set by their position.

If we forgot to pass them in then they’ll be undefined .

JavaScript isn’t picky when checking arguments.

The type can be anything, and we can skip any of them.

It’ll just do things that we don’t expect and fails silently if we don’t pass in what’s expected.

Conclusion

Functions are reusable pieces of code we can invoke.

for…in loops let us loop through objects and for…of loops let us loop through iterable objects.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Functions and Objects

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at functions and objects.

Iterators

Iterators can be created with generator functions in JavaScript.

For instance, we can write:

function* genFn() {
  yield 1;
  yield 2;
  yield 3;
}

We have a generator function as indicated by the function* keyword.

Then we can call it to return an iterator:

const gen = genFn();
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());

We called genFn to get an iterator.

Then we called next on the returned iterator.

And the next method will return the object with the value and done properties.

value has the value from yield .

And done is a boolean to indicate whether all the values are returned.

IIFE vs Blocks

We don’t need IIFEs for containing variables in blocks anymore.

We can use let and const to declare block-scoped variables.

So if we have:

(function() {
  var foo = 0;
}());
console.log(foo);

Then the console log will throw the ‘Uncaught ReferenceError: foo is not defined’ error.

We can do the same thing with let or const variables in blocks”

{
  let foo = 1;
  const bar = 2;
}

Arrow Functions

Arrow functions are great for creating callbacks.

For example, we often have to write code like:

$("#submit-btn").click(function(event) {
  validateForm();
  submit();
});

Arrow functions are a bit shorter and we won’t have to worry about the value of this in the function.

Instead, we can write:

$("#submit-btn").click((event) => {
  validateForm();
  submit();
});

We can write arrow functions in various ways. They’re:

  • No parameters: () => {...}
  • One parameter: a => {...}
  • More than one parameters: (a,b) => {...}

Arrow functions can have both statement block bodies or expressions.

We can have a statement block with:

n => {
  return n ** 2;
}

And we can have an expression with:

n => n ** 2;

Objects

Objects are the most central part of object-oriented programming.

It’s made of various properties and methods.

And properties may contain primitive values or other objects.

We can create an object by writing:

const person = {
  name: 'james',
  gender: 'male'
};

An object is surrounded by curly braces.

And name and gender are the properties.

The keys can be in quotation marks.

For instance, we can write:

const person = {
  'name': 'james',
  gender: 'male'
};

We need to quote property names if the property name is one of the reserved words in JavaScript.

We also need to quote them if they have spaces.

And if they start with a number, then we also need to quote them.

Defining an object with {} is called the object literal notation.

Elements, Properties, Methods, and Members

An array can have elements.

But an object has properties, methods, and members.

The object:

const person = {
  name: 'james',
  gender: 'male'
};

only has properties.

Properties are key-value pairs.

The value can be anything.

Methods are just properties with function values.

So if we have:

const dog = {
  name: 'james',
  gender: 'male',
  speak() {
    console.log('woof');
  }
};

Then speak is a method.

Hashes and Associative Arrays

Object properties can be added and remove dynamically, so we can use them as hashes or associative arrays.

Hashes and associative arrays are just key-value pairs.

Conclusion

We can create iterators with generators, and we can define objects with properties and methods.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Errors and Iterables

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at the error object and iterables.

Error Objects

JavaScript throw Error objects when an error is encountered.

They include various constructors.

They include EvalError, RangeError, ReferenceError, SyntaxError, TypeError, and URIError.

All of these constructors inherit from Error .

We can put code that may throw errors within the try block.

And we can catch the error in the catch block.

For instance, we can write:

try {
  foo();
} catch (e) {
  //...
}

If foo throws an error, then the catch block will catch the error.

e has the error object thrown.

We can get the name with e.name and the message with e.message .

We can add a finally clause to run code regardless of whether an error is thrown.

For instance, we can write:

try {
  foo();
} catch (e) {
  //...
} finally {
  console.log('finally');
}

ES6 Iterators and Generators

Iterators and generators are new constructs with ES6.

They let us create various types of iterable objects and use them.

For…of Loop

The for…of loop lets us iterate through any kind of iterable objects.

For instance, we can loop through an array with it by writing:

const iter = [1, 2];
for (const i of iter) {
  console.log(i);
}

Then we get:

1
2

We used const in the loop heading so that we can’t reassign the loop variable i to something else.

We can do the same thing for other iterable objects like strings:

for (const i of 'foo') {
  console.log(i);
}

then we get the individual characters as the values of i .

The for…of loop is used for iteration.

Iterators and Iterables

Iterators are objects that expose the next to get the next entry of a collection.

We can create an iterator with a generator function.

For instance, we can write:

function* genFunc() {
  yield 1;
  yield 2;
  yield 3;
}

yield returns the next item we want to return in the iterator by calling next.

Once we called next , then the generator function will be paused.

We can use it by writing:

const gen = genFunc();
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());

Then we get:

{value: 1, done: false}
{value: 2, done: false}
{value: 3, done: false}
{value: undefined, done: true}

We get each item that’s yielded with each next call.

The value has the yielded value, and done tells us whether the generator is done generating values.

An iterable is an object that defines its iteration behavior.

They can used with the for…of loops for iteration.

Built-in iterables include arrays and strings.

All iterable objects have the @@itrerator method, which has the property with Symbol.iterator as the key.

It must return an iterator with the next method.

So the simplest way is to use generators so that we can call next and return the values.

We can create an iterable by writing:

const obj = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  }
}

Then we can use the for…of loop by writing:

for (const i of obj) {
  console.log(i);
}

Then we get:

1
2
3

logged.

Conclusion

ES6 iterable objects like arrays and strings use iterators to return the values that it has.

They can also be iterated through with a for…of loop.

Error objects can be thrown by any code and we can catch them with try-catch-finally.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Doing Things with Functions

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at functions.

Running a Function

We can run a function by adding parentheses after its name.

It works regardless of how a function is defined.

For instance, if we have a function:

const sum = function(a, b) {
  return a + b;
};

Then we run it by writing:

sum(1, 2);

We pass in the numeric arguments sum expects.

Anonymous Functions

Anonymous functions are functions that have no name.

The sum function we had before had a function that had no name assigned to a variable.

This way, we can call it anywhere.

Callback Functions

Callback functions are functions that are called by other functions.

For instance, we can write:

function runAdd(a, b) {
  return a() + b();
}

The runAdd function calls the a and b functions.

Therefore, we have to pass 2 functions to it.

We can use it by writing:

const sum = runAdd(() => 1, () => 2)

We passed in a function that returns 1 and one that returns 2 as arguments.

Then we get 3 returned.

So sum is 3.

Callbacks are useful when we run async code.

We can call callback when the async code has its results.

We can also have synchronous callbacks to do repeated operations like with array methods like map , filter and reduce .

We can make our own map method by writing:

function map(arr, callback) {
  const result = []
  for (const a of arr) {
    result.push(callback(a));
  }
  return result;
}

Then we can use it by writing:

const result = map([1, 2, 3], (x) => x * 2);

Then result would be [2, 4, 6] .

map takes an array arr , loops through each entry with the for-of loop, and call callback on each entry with each entry.

Immediate Functions

Immediate functions are functions that are called immediately after they’re defined.

For instance, we can write:

(
  function() {
    console.log('foo');
  }
)();

Then we created a function and called it immediately.

We should surround it with parentheses so we know we’re calling it.

We can also write:

(function() {
  console.log('foo');
})();

And we can get the returned value and write:

const result = (function() {
  //...
  return {
    //...
  }
}());

We return some result in the function and assigned that to result .

Inner (Private) Functions

Functions are like any other variable, so we can put them in another function.

For instance, we can write:

function outer(param) {
  function inner(a) {
    return a * 100;
  }
  return inner(param);
}

We have a inner function that returns its parameter multiplied by 100.

Then we return the result.

The benefit of having inner functions is that the variables inside the function can’t be accessed from the outside.

But the inner function can access variables from the outer function.

This is a big benefit since we don’t have to define variables at the global scope.

Conclusion

There’re many benefits to defining private functions.

We can also define immediately invoked functions to return something.

Functions can be anonymous and can be parameters of another function.