JavaScript, The Interesting Parts

Concepts worth writing down while reading ‘Eloquent JavaScript’

Object-oriented JavaScript

  • Constructor

In JavaScript, calling a function with the new keyword in front of it causes it to be treated as a constructor. The constructor will have its this variable bound to a fresh object. An object created with new is said to be an instance of its constructor.

1
2
3
4
5
6
function Cat(type) {
this.type = type;
}

var persianCat = new Cat("Persian");
var scottishCat = new Cat("Scottish");
  • Method Overriding

Actually, it is called property overriding. When you add a property to an object, whether it is present in the prototype or not, the property is added to the object itself, overriding the value ‘inherited’ from the parent object.

1
2
3
4
5
6
7
8
9
10
11
12
13
Cat.prototype.hair = "short short short";
console.log(Cat.prototype.hair);
// > short short short

persianCat.hair = "long long long";
console.log(persianCat.hair);
// > long long long

console.log(Cat.prototype.hair);
// > short short short

console.log(scottishCat.hair);
// > short short short
  • Polymorphism

The concept of polymorphism applies to JavaScript as well. For example, some of the standard prototypes define their own version of toString so they can create a string that is more meaningful than “[object Object]”.

  • Getters and Setters

Unlike standard object-oriented languages, JavaScript has specific syntax for creating getters and setters.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var cat = {
type: "Ragdoll",
get getType() {
return this.type;
},
set setType(value) {
this.type = value;
}
}

console.log(cat.getType);
// > Ragdoll
cat.setType = "Persian";
console.log(cat.getType);
// > Persian
  • Inheritance

Use Object.create() to create a new object with prototypes inherited from another object, forming a parent-child relationship. This approach is especially useful when writing custom exceptions.

1
2
3
4
5
6
7
8
function RagDoll(type) {
Cat.call(this, type);
}

RagDoll.prototype = Object.create(Cat.prototype);
RagDoll.habit = function() {
// ...
}

Function

  • Scope

JavaScript code is interpreted from top to bottom, executed in the order it appears. Function definitions and var variable declarations are conceptually hoisted to the top of the their current scope, however. They are not part of the regular top-to-bottom flow of control. So the following code runs without errors.

1
2
3
4
5
6
7
console.log("Hello from ", foo());

function foo() {
return "foo";
}

// > Hello from foo

But, what if you put such function definition inside a conditional block, like the one shown below? It turns out that different JavaScript engines interpret differently in that situation, and the latest standard actually forbids it.

1
2
3
4
5
6
function example() {
function a() {} // fine
if (something) {
function b() {} // noop
}
}
  • Module

Functions are the only things in JavaScript that create a new scope. So if we want our modules to have their own scope, we will use functions. The parentheses wrapping around the function definition is a trick to force the function to be interpreted as an expression, making it unavailable to be called as a regular function.

1
2
3
4
5
6
7
8
9
(function() {
var hundred = 100;
function square(x) {
return x * x;
}

console.log(square(hundred));
})();
// > 10000

Optional Arguments

If you pass too many arguments, the extra ones are ignored. If you pass too few, the missing parameters simply get assigned the value undefined.

1
2
// only the first argument is accepted
alert("Hello", "I'm an alert", "How you doing");

Properties

1
2
null.length;
// > TypeError: Cannot read property 'length' of null

All JavaScript values have properties, except null and undefined. If you try to access a property on one of these nonvalues, you will get the TypeError.

Events

  • stopPropagation

Event handlers registered on elements with children will also receive certain events that happen in the children. Say, if a button inside a paragraph is clicked, it will also trigger the click event on that paragraph element. The more specific handler – the one on the button – gets to go first. The event is said to propagate outward. If we want to prevent handlers further up from the receiving event, we call stopPropagation method on that event.

  • preventDefault

Call preventDefault if you don’t want the normal behavior to happen, especially when you have already taken care of handling the event. The can be useful when you want to implement your own keyboard shortcuts or right-click context menu.