# JavaScript/OOP-classical

The heart of JavaScript's object-based approach is the linked list of objects where every object acts as a prototype for its successor. It is revealed when using the classical syntax.

## Construction

There are different syntactical ways to construct objects. They are not identical, but even looking behind the scene, you will see only slight differences in their semantics. All variants create a set of key/value pairs, the properties. This set of properties composes an object.
The three language constructs literal, new, and Object.create create simple or complex objects. Such objects can be subsequently extended by assigning values to additional properties.

### Functions

The 'value' part of the key/value pairs can contain not only values of primitive data types. It's also possible that they contain functions. (When functions are the value-part of a property, they are called a method.)

### new

In the previous example, we defined objects containing a property with a value and another with a method. Both parts are accessible by the usual dot-notation. But they miss a smart syntactical feature: it's not possible to define their properties directly with the first invocation. Something like const x = new obj_1("valueOfProperty") or const mike = new Person("Mike") will not run because such a syntax misses the name of the property.
We change and extend the above example to allow this syntax, the new operator in combination with parameters. To do so, we define functions (which are also objects) that contain and store variables as well as ('inner') functions/methods.
The function Person takes parameters as every other function. The first letter of its name is written in uppercase, but this is only a convention and not mandatory. If the function is invoked with the new operator, in the first step, a new object is constructed. Within the function, you can refer to the new object with the keyword 'this', e.g., to store the given parameters. If, in addition, the function shall offer some functionality in the form of ('inner') functions, you define them and store a reference to them in 'this' under an arbitrary name - in the example, it is the 'show' function.
After the function is defined, you can use them via the new operator to create individual objects (instances). Such individual objects store the given arguments and offer the internally defined functions.
Please note that the new Person(...) statement is different from the usual invocation of a function without the new operator: Person(...). The new is necessary to indicate that the construction of an object must be done before the body of the function can run. Without new, the JavaScript engine doesn't create an object, and the use of 'this' will fail.

### Predefined data types

Many predefined data types (Date, Array, ...) are defined in the above way. Therefore you can use the new operator for their creation: const arr = new Array([0, 1, 2]). The arguments are stored somewhere in the newly created object. Here, it's only a single one, a literally expressed array. It gets decomposed, and the array elements are stored. Some derived properties are computed, e.g., the length, and a lot of methods are provided, e.g., push and pop. All in all, the internal structure often differs from the externally visible form.
In addition to this unified syntax with new there are some syntax variants that are special according to the intended data type. E.g., for Array you can use const arr = [0, 1, 2]. But it's just an abbreviation for: const arr = new Array([0, 1, 2]).

## Inheritance

This chapter shows different syntactical possibilities for how to arrange objects in a hierarchy.

### setPrototypeOf

If you have defined independent objects, you can subsequently link them together so that they build a parent/child relationship afterward. The crucial function is setPrototypeOf. As its name suggests, the function sets one object as the prototype of another object. By this, the parent's properties, including functions, are accessible to the child.
After setPrototypeOf is successfully executed, the child object 'extends' the parent object. It gets access to all properties of the parent object, as shown in line 12.
How does it work? Every single object contains a property named '__proto__', even if it is not mentioned anywhere in the source code. Its value refers to the object which acts as its 'parent'. Also, the 'parent' contains such a '__proto__' property, and so on. At the highest level, the value is null to flag the end of the hierarchy. All in all, it's a 'linked list' of objects. It is called the prototype chain. It is the heart of JavaScript's implementation of OOP: 'parents' act as 'prototypes' for the referencing objects - for all system objects as well as for all user-defined objects.
The JavaScript engine uses the prototype chain whenever it searches for any property. When the engine doesn't find it, it switches to the next higher level and repeats the search.
This applies in the same way to the case that a function is searched.
After line 13, the method func_1 can be invoked by the child object, although it is defined by the parent.

### new

Suppose you know in advance that one object shall act as a child of another object. In that case, the new operator offers the possibility to define the dependency from the beginning. The already existing object can be given as a parameter to the creation process. The JavaScript engine will combine this existing object with the newly creating object by the exact same mechanism, the '__proto__' property.

### Object.create

This pre-known hierarchical relation can also be realized with the Object.create method.

### A distinction to class-based approaches

There are some distinctions between JavaScript's prototype-based approach and class-based approaches. One of them regarding inheritance is shown here.
After creating a prototype hierarchy and instances with one of the above methods, you can modify the 'parent' instance to manipulate all 'child' instances at once.
The statement in line 17 adds the property 'property_2' - virtually - to all instances at once. Whenever 'property_2' is acquired by a subsequent statement, the JavaScript engine will follow the prototype chain. First, in the 'child' instances, it will not find 'property_2'. But following the prototype chain, it will find it in the 'parent' instance. For the 'child' instances, it doesn't make a difference whether the property is in its own space or in its parent space.
The distinction to a class-based approach is that not only the value of the new property is added. Also, the structure of all instances is expanded: the added property hasn't existed at all before line 17.

## Check object hierarchy

There are different ways to check the hierarchy of data types of any variable or value.

### getPrototypeOf

The getPrototypeOf method gives you a chance to inspect the hierarchy. It returns the parent object itself, not its data type. If you are interested in the data type of the parent, you must check the parent's data type with one of the other operators.
Or, follow the prototype chain in a flexible loop:

### instanceof

The instanceof operator tests whether the prototype chain of a variable contains the given data type. It returns a boolean value.

### typeof

The typeof operator returns a string showing the data type of its operand. But it is limited to detect only certain data types respectively their parent object. Possible return values are: "undefined", "object", "boolean", "number", "bigint", "string", "symbol", "function".

## Exercises

    ... are available on another page (click here).

## See also

* MDN: Prototypes