Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Observers and Tests

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 some basic design patterns and tests.

Observer Pattern

The observer pattern is where we observe the changes from the one source by subscribing to an object and publish the changes to the observers that subscribed when there’re changes.

We can create an object that takes observers and publish changes to them by writing:

const observer = {
  subscribers: [],
  addSubscriber(callback) {
    if (typeof callback === "function") {
      this.subscribers.push(callback);
    }
  },

  removeSubscriber(callback) {
    const index = this.subscribers.findIndex(s => s === callback);
    this.subscribes.splice(index, 1);
  },

  publish(obj) {
    for (const sub of this.subscribers) {
      if (typeof sub === 'function') {
        sub(obj);
      }
    }
  },
};

We create an observer object that takes callbacks.

callback is a function that we add to the subscribers array.

Also, we have the removeSubscriber array to remove a callback.

publish takes an object with something to publish and callbacks the callbacks in the this.subscribers array to publish the changes.

Then we can use it by writing:

const callback = (e) => console.log(e);
const callback2 = (e) => console.log(2, e);
observer.addSubscriber(callback);
observer.addSubscriber(callback2);
observer.publish('foo')

We created 2 callbacks and add them to the subscribers array with the addSubscriber method.

Then we call publish to call the callbacks, which log the changes.

We should see:

foo
2 "foo"

logged in the console log.

The observer pattern is good since there’s not much coupling between the callbacks and the observer object.

We just call the callback when there’s some information to send to them.

The callbacks know nothing about the observer .

Testing

Testing is an important part of writing JavaScript apps.

We can make our lives easier by writing tests that run automatically.

Not having enough tests is a bad idea.

With tests, we make sure that the existing code behaves as per our specifications.

And any new code changes didn’t break existing behavior defined by our spec.

With tests, we don’t have to test everything ourselves by hand.

Also, we won’t have to check everything ourselves again when we refactor.

If our changes make the tests fail, then we know there’s something wrong.

Unit Testing

Unit testing is what we have the most of.

They’re short and they run fast.

They test the output given some input.

And they should be self-explanatory, maintainable and readable.

They should also work the same way in any order.

Test-Driven Development

Test-driven development is used a lot recently,

The methodology workflow starts by writing some tests that fail.

And then we write code to make the tests pass.

Then we run the tests again to see if they pass.

And then we refactor our code and make sure our tests still pass.

Behavior Driven Development

Behavior-driven development is a methodology where we create tests to test how our code behaves.

We test with some inputs and check th outputs.

Conclusion

We can create unit tests to test our code.

Also, the observer pattern lets us create loosely coupled code that communicates from the observer to another object.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Lazy Definition and Private Variables

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 some basic coding and design patterns.

Lazy Definition

The lazy definition pattern is where we assign the function to a property when we run it.

For instance, we can write:

const APP = {};
APP.click = {
  addListener(el, type, fn) {
    if (el.addEventListener) {
      APP.click.addListener = function(el, type, fn) {
        el.addEventListener(type, fn, false);
      };
    } else if (el.attachEvent) {
      APP.click.addListener = function(el, type, fn) {
        el.attachEvent(`on${type}`, fn);
      };
    } else {
      APP.click.addListener = function(el, type, fn) {
        el[`on${type}`] = fn;
      };
    }
    APP.click.addListener(el, type, fn);
  }
};

We have the addListener method which runs when we run the APP.click.addListener method.

We can set the function according to which one is available.

Configuration Object

We can create a configuration object to let us get configuration from there.

Objects are better than parameters because their order doesn’t matter.

We can also easily skip parameters that we don’t want to add.

It’s easy to add an optional configuration.

The code is more readable because the config’s object’s properties are in the code.

For example, instead of writing:

APP.dom.CustomDiv = function(text, color) {
  const div = document.createElement('div');
  div.color = color|| 'green';
  div.textContent = text;
  return div;
};

We write:

APP.dom.CustomDiv = function({
  text,
  color = 'green'
}) {
  const div = document.createElement('div');
  div.color = color;
  div.textContent = text;
  return div;
};

We destructured the object properties so that we can use the variables.

It’s shorter and cleaner.

And the order doesn’t of the properties don’t matter.

We just pass in an object as the parameter to use it:

new APP.dom.CustomDiv({ text: 'click me', color: 'blue' })

It’s easy to switch the parameters’ order if they’re in an object.

All the properties should be independent and optional.

Private Properties and Methods

We can keep properties and methods with JavaScript by keeping them in an object.

For instance, we can write:

APP.dom.CustomDiv = function({
  text,
  type = 'sumbit'
}) {
  const styles = {
    font: 'arial',
    border: '1px solid black',
    color: 'black',
    background: 'grey'
  };

  const div = document.createElement('div');
  div.styles = {
    ...div.styles,
    ...styles
  };
  div.type = type;
  div.textContent = text;
  return div;
};

We have the styles object that has the styles we want to apply to the div.

Since it’s inside the function, we can’t change it from the outside.

We can also add a method to set the styles inside the method:

APP.dom.CustomDiv = function({
  text,
  type = 'sumbit'
}) {
  const styles = {
    font: 'arial',
    border: '1px solid black',
    color: 'black',
    background: 'grey'
  };

  const div = document.createElement('div');
  const setStyles = (el) => {
    el.styles = {
      ...el.styles,
      ...styles
    };
  }

  div.type = type;
  div.textContent = text;
  setStyles(div);
  return div;
};

We have the setStyles private function that can only be called inside the CustomDiv constructor.

Conclusion

We can assign fu7nctions to a property when we call them.

Also, we can keep values private by putting them inside the function.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — JSON vs XML and Singletons

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 some basic coding and design patterns.

Use JSON

JSON is a popular lightweight format for exchanging data.

It’s better than XML since we can convert between JSON string and JavaScript objects easily.

An example of a JSON string includes:

{
  'a': 1,
  'b': 2,
  'c': 3
}

XML code is like:

<?xml version="1.0" encoding="UTF-8"?>
<response>
   <name>james</name>
   <books>
      <book>foo</book>
      <book>bar</book>
      <book>baz</book>
   </books>
</response>

It’s hard to convert XML code into JSON with JavaScript.

We have to install a library to do it.

But we can convert between a JSON string and an object literal with JSON.parse and JSON.stringify .

Also, XML code is longer with all the opening and closing tags.

JSON parsing and stringifying methods are also available in standard libraries of other languages like PHP.

Higher-Order Functions

Functional programming is confined to a limited set of languages.

JavaScript is one of the programming languages that have some functional programming features.

Higher-order functions are one of the basic features of functional programming.

A higher-order function is a function that takes one or more functions as arguments or returns a function as a result.

JavaScript functions can take functions as arguments and return functions.

They’re treated like other objects.

For instance, the array instance’s map method takes a function to let us map array entries to something else.

For instance, we can write:

[1, 2, 3, 4, 5].map(a => {
  return a ** 2;
})

We square each array entry and return an array with the squared entries.

The function we passed in is called on each entry and the returned result is added to the returned array.

We can write higher-order functions easily with arrow functions.

For instance, instead of writing:

function add(x) {
  return function(y) {
    return y + x;
  };
}
const add5 = add(5);

We write:

const add = x => y => y + x;
const add5 = add(5);

It’s much shorter and cleaner.

In both add functions, we take the parameter and return a function that takes a parameter y , add that with x and returns it.

Design Patterns

Design patterns are commonly-used language-agnostic ways for organizing our code.

The Gang of Four book is the most popular book with design patterns.

There’re several kinds of design patterns.

Creational patterns deal with how objects are created.

Structural patterns deal with how different objects are composed to provide new functionality.

Behavioral patterns provide us with ways for objects to communicate with each other.

Singleton Pattern

Singleton pattern is a creational design pattern.

In the pattern, we create only one object from any kind of class.

In JavaScript, we can do this simply with an object literal.

For instance, we can write:

const single = {};

to create an object literal.

Conclusion

We should use JSON for communication since it’s easier to serialize and parse.

Also, higher-order functions are used everywhere in JavaScript.

And we can create singleton objects with object literals.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Separating Behavior

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 some basic coding and design patterns.

Coding and Design Patterns

To organize our code in ways that we can work with them easily, we got to follow some patterns that allow that to happen.

Many people have thought of this problem, so we can follow existing patterns mostly.

Coding patterns are some best practices we can follow to improve our code.

Design patterns are language-independent patterns that are popularized by the Gang of Four book.

Separating Behavior

The building blocks of a web page includes HTML, CSS, and JavaScript code.

The content should be in the HTML code.

They have the markup to describe the meaning of the content.

For instance, we use ul for lists and li for list items and so on.

HTML code should be free from any formatting elements.

Visual formatting belongs to the presentation layer and should be achieved with CSS.

The style attribute shouldn’t be used for formatting.

Presentational HTML tags also shouldn’t be used.

Tags should be used form their meaning.

So section for dividing the text into sections, aside for a sidebar etc. should be used instead of div for everything.

Presentation

To make our pages presentable we can reset the browser defaults to be the same across all browsers.

Popular CSS frameworks like Bootstrap will do this.

Behavior

Any dynamic behavior should be written in the JavaScript code.

The JavaScript should be in scripts that are in external files in script tags.Inline attributes like onclick , onmouseover , etc. shouldn’t be used.

We should minimize the number of script tags so less JavaScript code has to be loaded.

Inline event handlers should be avoided to keep JavaScript code outside of HTML code.

CSS expressions shouldn’t ve used to keep compatibility.

To separate behavior, we can separate our form submission code from the form itself.

For example, we can write the following HTML:

<body>
  <form id="nameForm" method="post" action="server.php">
    <fieldset>
      <legend>name</legend>
      <input name="name" id="name" type="text" />
      <input type="submit" />
    </fieldset>
  </form>
  <script src="script.js"></script>
</body>

to create a form.

Then we can listen to the submit event in script.js :

const nameForm = document.querySelector('#nameForm');
nameForm.addEventListener('submit', (e) => {
  const el = document.getElementById('name');
  if (!el.value) {
    e.preventDefault();
    alert('Please enter a name');
  }
});

We get the form with querySelector .

Then we listen to the submit event with addEventListener .

In the event handler, we get the name field by its ID.

If there’s no value, we stop the submission with preventDefault() .

And then we display an alert.

Conclusion

We should separate content, styling, and dynamic behavior in our code.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Removing Nodes and Document

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 DOM and some useful document properties.

Removing Nodes

We can call the removeChild method to remove a child node.

For instance, if we have the following HTML:

<body>
  <p class="opener">foo</p>
  <p><em>bar</em> </p>
  <p id="closer">baz</p>
  <!-- the end -->
</body>

We can remove the node by writing:

const p = document.querySelector('p');
const removed = document.body.removeChild(p);

then the p element is removed from the body with removeChild .

The removed node is returned.

There’s also the replaceChild method that lets us remove a node and puts another one in place.

For example, we can write:

const p1 = document.querySelector('.opener');
const p2 = document.querySelector('#closer');
const removed = document.body.replaceChild(p1, p2);

to replace the node with ID closer with the one that has class opener .

HTML — only DOM Objects

There are various ways to access HTML-only DOM objects.

We can access than with some properties that are available in modern browsers.

document.body has the body element.

It’s one of the elements that are in the DOM Level 0 spec that’s moved to the HTML extension of the DOM spec.

Other properties includes the document.images to get the img elements.

document.applets lets us get the applet elements.

document.links gets us the link elements.

document.anchors gets us anchor a elements.

document.forms lets us get the forms.

So:

document.forms[0];

is the same as:

document.getElementsByTagName('forms')[0];

If we have the following form:

<form>
  <input name="name" id="name" type="text" size="50" maxlength="255" value="Enter name" />
</form>

Then we can get the input element and set the value with:

document.forms[0].elements[0].value = 'foo';

We can disable the input with:

document.forms[0].elements[0].disabled = true;

And we can get the input by its name attribute with:

document.forms[0].elements['name'];

or:

document.forms[0].elements.name;

The document.write() Method

The document.write method lets us write HTML to the page.

For example, we can write:

document.write(`<p>${new Date()}</p>`);

to write the date to the screen.

If we load the page, document.write will replace all the content on the page.

Cookies, title, referrer, and domain

We can get and set the client-side cookies with the document.cookie property.

It’s a string that has some key-values and the expiry date.

When a server sends a page to the client, it may send the Set-Cookie HTTP response header back with the cookie.

The document.title property lets us get and set the title of the page, so we can write:

document.title = 'title';

The document.domain property has the domain of the current page.

We may get something like “jsfiddle.net” if we are in there.

We can’t set it to a different domain, so if we’re in jsfiddle.net, then we can’t write:

document.domain = 'example.com'

We’ll get the error:

Uncaught DOMException: Failed to set the 'domain' property on 'Document': 'example.com' is not a suffix of 'jsfiddle.net'.

This is good for protecting users. We don’t want to let scripts go to any domain they like.

Conclusion

We can remove nodes with DOM methods.

Also, we can use various properties and methods of document to manipulate a document.