Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Proxies, Functions, and Built-in 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 JavaScript metaprogramming with proxies and built-in browser objects.

Proxies and Function Traps

We can intercept function calls with the get and apply operations.

For instance, we can create a handler by writing:

const person = {
  name: "james",
  foo(text) {
    console.log(text);
  }
}

const proxy = new Proxy(person, {
  get(target, propKey, receiver) {
    const propValue = target[propKey];
    if (typeof propValue !== "function") {
      return propValue;
    } else {
      return function(...args) {
        return propValue.apply(target, args);
      }
    }
  }
});

proxy.foo('james')

We have the person object that we control with the get method.

target is the object we’re controlling.

In this case, it’s the person object.

propKey is the property key.

We check if the property is a function.

If it’s not, we return whatever value it has.

Otherwise, we call the function with this being target with the arguments.

And we return the result.

The Browser Environment

The browser environment is controlled with JavaScript.

It’s the natural host for JavaScript programs.

Including JavaScript in an HTML Page

We can include JavaScript in an HTML page with the script tag.

For instance, we can write:

<!DOCTYPE>
<html>

<head>
    <title>app</title>
    <script src="script.js"></script>
  </head>

  <body>
    <script>
      let a = 1;
      a++;
    </script>
  </body>

</html>

We have a script tag with src set to script.js .

And we also have an inline script with JavaScript code inside it.

BOM and DOM

JavaScript code on a page has access to various objects.

They include core ECMAScript objects, which are ones like Array , Object , etc.

DOM are objects that have to do with the current page.

BOM has objects that deal with everything outside the page like the browser window and desktop screen.

The DOM is standardized in various W3C specs.

But the BOM isn’t in any standard.

BOM

The BOM is a collection of objects that gives us access to the browser and the computer screen.

The objects are accessible through the global window object.

The window Object

The window object is a global object provided by the browser environment.

For instance, we can add a global variable by writing:

window.foo = 1;

Then foo is 1.

Some core JavaScript functions are part of the window object.

For instance, we can write:

parseInt('123');

then we get 123.

It’s the same as:

window.parseInt('123');

These can vary from one browser to another, but they’re implemented consistently and reliably across all major browsers.

The window.navigator Property

The navigator property has some information about the browser and its capabilities.

One is the navigator.userAgent property.

For instance, we can write:

window.navigator.userAgent

then we get the user agent string.

We may get a string like:

"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.52"

returned.

We can use this to check for which browser.

For instance, we can write:

if (navigator.userAgent.indexOf('MSIE') !== -1) {
  //...
} else {
  //...
}

to check if a script is running in Internet Explorer.

But it’s a bad way to check for browser features since the user agent can be spoofed.

We can just check for the feature we want directly:

if (typeof window.addEventListener === 'function') {
  // ...
} else {
  // ...
}

Conclusion

Browsers have various built-in objects we can use.

Also, we can use proxies to control functions.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Properties of Window

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 built-in properties of window .

The window.screen Property

The window.screen property lets get information about the browser’s screen.

We can get the color depth with:

window.screen.colorDepth;

And we can get the screen’s width with:

screen.width;
screen.availWidth;

width is the whole screen and availableWidth subtracts the widths of the menus and scrollbars, etc.

We can get the heights the same way with:

screen.height;
screen.availHeight;

Some devices also have the devicePixelRatio property:

window.devicePixelRatio

which tells us the trio between the physical pixels and device pixels in retina displays.

window.open()/close() Method

The window.open method lets us open a new browser window.

Various policies and settings of the browser may prevent us from opening popups to curb popup ads.

But we should be able to open a new window if it’s initiated by the user.

If we try to open a window when the page loads, it’ll probably be blocked since the user didn’t open the window.

The window.open() method takes a few parameters.

The first is the URL to load in a new window.

The name of the new window can be used as the value of the form’s target attribute.

A comma-separated list of features are also arguments, which include resizable to indicates whether the popup is resizable.

The width is the width of the popup window.

status is indicates whether the status bar should be visible.

For instance, we can write:

const win = window.open('http://www.example.com', 'example window',
'width=300,height=300,resizable=yes');

We call the open method with the URL, the title, and a string with the window size and whether it’s resizable.

win has the close method to let us close the window.

The window.moveTo() and window.resizeTo() Methods

The window.moveYo method lets us move the browser window to the given screen coordinates of the top-left corner.

For instance, we can write:

window.moveTo(100, 100)

to move the window.

We can also call the moveBy method to move the window by the given number of pixels across and down from its current location.

For instance, we can write;

window.moveBy(10, 10):

to move a window right and down by 10 pixels.

We can also pass in negative numbers to move in the opposite direction.

The window.resizeTo and window.resizeBy methods accept the same parameter as the move methods.

But they resize the window instead of moving it.

The window.alert(), window.prompt(), and window.confirm() Methods

alert is a method that takes a string and shows the alert with the text we pass in.

confirm lets us create a dialog box with the text we want to display.

The user can click OK or Cancel to dismiss the dialog box.

The value will be returned by the confirm function.

It’ll return true if we click OK and false otherwise.

So we can write:

const answer = confirm('Are you sure?');

Then we can get the answer after the user clicks on the button.

It’s handy for confirming user actions.

So we can write:

if (confirm('Are you sure?')) {
  // ...
} else {
  // ...
}

The prompt lets us show a dialog with some question text and let the user enter something into an input.

The inputted value will be returned as a string.

If it’s empty then it returns an empty string.

It returns null if the user clicks cancel, X, or press the Esc key.

We can use it by writing:

const answer = prompt('Are you sure?');

answer has the answer that’s entered.

Conclusion

window has many methods we can use.

They include methods to open a window, open alerts and prompts, and more.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Metaprogramming and Proxies

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 JavaScript metaprogramming with proxies.

Metaprogramming and Proxies

Metaprogramming is a programming method where a program is aware of its structure and manipulating itself.

There’re multiple ways to do metaprogramming.

One is introspection. This is where we have read-only access to the internals of a program.

Self-modification is making structural changes to the program.

Intercession is where we change language semantics.

In JavaScript, we can do this with proxies.

They let us control how objects are accessed and set.

Proxy

We can use proxies to determine the behavior of an object.

The object being controlled is called the target.

We can define custom behaviors for basic operations on an object like property lookup, function call, and assignment.

A proxy needs 2 parameters,

One is the handler, which is an object with methods to let us change the behavior of object operations.

Target is the target that we want to change the operations to.

For instance, we can create a proxy to control an object by writing:

const handler = {
  get(target, name) {
    return name in target ? target[name] : 1;
  }
}
const proxy = new Proxy({}, handler);
proxy.a = 100;

console.log(proxy.a);
console.log(proxy.b);

We created a proxy with handler with the handler object.

The get method lets us control how properties are retrieved.

target is the object that we’re controlling.

The name is the property name we want to access.

In the get method, we check if the name proxy exists.

If it does we return the target value, otherwise we return 1.

Then we create a proxy with the Proxy constructor.

A first argument is an empty object.

handler is our handler for controlling the operations.

proxy.a is defined, so its value is returned.

Otherwise, we return the default value.

Also, we can use proxies to validate values before setting them to an object.

For instance, we can trap the set handler by writing:

const ageValidator = {
  set(obj, prop, value) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError('age must be a number');
      }
      if (value < 0 || value > 130) {
        throw new RangeError('invalid age range');
      }
    }
    obj[prop] = value;
  }
};
const p = new Proxy({}, ageValidator);
p.age = 100;
console.log(p.age);
p.age = 300;

We have the set method with the obj , prop , and value parameters.

obj is the object we want to control.

prop is the property key.

value is the property value we want to set.

We check if prop is 'age' so that we validate the assignment of the age property.

Then we check if it’s an integer and if it’s not we throw an error.

We also throw an error if it’s out of range.

Then we create a proxy with the Proxy constructor with the ageValidator as the handler and an empty object to control.

Then if we try to set p.age to 300, we get a RangeError .

Conclusion

Proxies let us control how object properties are retrieved and set.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — DOM Traversal Shortcuts

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.

DOM Access Shortcuts

Using childNodes, parentNode, nodeName, nodeValue, and attributes properties let us traverse the DOM.

However, they’re very inconvenient to use if we have any complex document.

Deeper nodes are hard to access and there’s no easy way to search for the items we want.

We have various shortcut methods that let us find the DOM element we want in an easier way.

The methods include getElementsByTagName(), getElementsByName(), getElementById() , querySelector() , and querySelectorAll() .

The getElementsByTagName method lets us get all the elements with a given tag name.

For instance, with the given HTML:

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

We can write:

document.`getElementsByTagName('p');`

to returns a NodeList of p elements.

We can get the number of p elements with the length property:

document.`getElementsByTagName('p').length`

And we can get elements by index:

document.`getElementsByTagName('p')[0]`

We can get the HTML with innerHTML :

document.`getElementsByTagName('p')`[0].innerHTML;

and we get 'foo' .

getElementById lets us get an element by ID.

We can write:

document.getElementById('closer');

to get the element with ID closer .

getElementByClassName lets us get elements by class name.

querySelector lets us get an element with a given CSS selector.

And querySelectorAll lets us get all elements with the given CSS selector.

Siblings, Body, First, and Last Child

The nextSibling and previousSibling properties are 2 convenient properties to navigate the DOM tree if we have reference to one element.

So if we have:

const p = document.getElementById('closer');

We can write

console.log(p.previousSibling)

And get:

#text

And we can use it again by writing:

console.log(p.previousSibling.previousSibling)

and we get the p element above it.

We can mix previousSibling and nextSibling .

For instance, we can write:

p.previousSibling.nextSibling

A DOM node also has the firstChild and lastChild properties.

For instance, we can use:

document.body.firstChild;

to get the first child node of the body.

firstChild is the same as childNodes[0] .

lastChild gets the last child node of a node.

We can use:

document.body.lastChild;

to get the last child node of the body.

lastChild is the same as childNodes[childNodes.length — 1] .

Modifying DOM Nodes

We can modify DOM nodes by assigning a value to the innerHTML property/

For instance, we can write:

const p = document.getElementById('closer');
p.innerHTML = 'closer';

We can also set the HTML string as the value of innerHTML :

const p = document.getElementById('closer');
p.innerHTML = '<em>closer</em> closer';

We can also change the content of a node by assigning a value to the nodeValue property:

const p = document.getElementById('closer');
p.nodeValue = 'closer';

Conclusion

We can get DOM nodes with various shortcut methods.

Also, we can set the content with various properties.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — DOM Traversal

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.

Accessing DOM Nodes

We can access DOM nodes with built-in objects in the browser.

The document node gives us access to the current document.

We can see the properties of it with the console.dir method:

console.dir(document);

We can use the nodeType property to get the type of node.

ndoeName has the node’s name.

nodeValue has the value, which is the text for text nodes for example.

The:

document.nodeType;

returns 9.

There’re 12 node types, which are represented by integers.

The most common is 1 for element, 2 attributes, and 3 for text.

document.nodeName

returns '#document' .

And document.nodeValue is null .

documentElement

The document.documentElement property gives us the HTML element.

The nodeType is 1 since it’s an element.

We can see that with:

document.documentElement.nodeType

We can get the nodeName with:

document.documentElement.nodeName

and get the tag name with:

document.documentElement.tagName

They both return 'HTML' .

Child Nodes

We can get child nodes from the document object.

Also, we can check if there’re any child nodes with the hasChildNodes method.

For example, we can write:

document.documentElement.hasChildNodes();

and we get true .

The childNodes property has the length property to get the number of child nodes of a DOM node.

For example, we can write:

document.documentElement.childNodes.length;

And we can get the child nodes by its index:

document.documentElement.childNodes[0];
document.documentElement.childNodes[1];

etc.

To get the parent node, we can use the parentNode property:

document.documentElement.childNodes[1].parentNode;

they all return some element.

In the last example, the HTML element is returned.

For instance, if we have:

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

Then console.log(document.body.childNodes.length) logs 10 since we have the HTML elements, attribute nodes, text nodes, and comment nodes.

Attributes

We can check whether an element has attributes with the hasAttributes method.

For instance, we can write:

console.log(document.body.childNodes[1].hasAttributes())

then we get true .

If it’s true then the node has attributes.

We can get the attributes with the attributes .

For instance, we can write:

console.log(document.body.childNodes[1].attributes[0].nodeName)

then we get 'class'.

nodeName get the name of the attribute.

We can also use the nodeValue property to get the attribute value.

So we can write:

console.log(document.body.childNodes[1].attributes['class'].nodeValue)

We can also get the attribute with the getAttribute method:

console.log(document.body.childNodes[1].getAttribute('class'))

Accessing the Content Inside a Tag

We can get content inside a tag.

To do that, we can use the textContent property to get the text content inside a tag.

So we can write:

console.log(document.body.childNodes[1].textContent)

then we get 'foo' .

Also, we can get the innerHTML property to get the HTML content in an HTML element node:

console.log(document.body.childNodes[3].innerHTML)

and we get:

<em>bar</em>

Like other elements, we can get the length , nodeName and nodeValue .

For instance, we can write:

console.log(document.body.childNodes[1].childNodes.length)

to get the length of the child nodes and:

console.log(document.body.childNodes[0].nodeName)

which logs ‘#text’ and:

console.log(document.body.childNodes[1].childNodes[0].nodeValue)

and we get 'foo' .

Conclusion

We can use various properties to get DOM nodes and attributes.