JavaScript: One Example Would Have Changed Everything

Computer ScienceJavaScriptObject Oriented ProgrammingProgramming LanguagesSoftware Engineering

JavaScript: One Example Would Have Changed Everything

A Personal Retrospective

In the late 1990s, many developers (myself included) encountered JavaScript through the lens of Java. The name alone suggested classes, inheritance hierarchies, and object-oriented (OO) patterns that were already familiar—but JavaScript did not actually work that way. As a result, its true model remained obscure.

Looking back, it is striking how a single, well-chosen example could have clarified everything. A simple data structure—implemented cleanly and honestly in the prototype-based style—would have revealed what JavaScript was really about.

This paper presents such an example: a singly linked list, written in plain ES1-style JavaScript, without classes, without syntactic sugar, and without conceptual compromise.

The Core Idea: Objects Linked by Delegation

Prototype-based object orientation is not about types or inheritance trees. It is about:

A linked list is ideal here, because it is itself a structure built from linked objects.

The Node: A Minimal Stateful Object

function LinkedListNode(value) {
    this.value = value;
    this.next = null;
}

This constructor does exactly one thing: create an object with state.

There is no behavior here. No methods. No inheritance. Just data.

Key points:

The new operator is essential here: it allocates a new object, binds it to this, and links it to LinkedListNode.prototype. Without new, the constructor doesn’t create a fresh instance.

This strict separation is intentional.

The List Object: State Without Behavior (Yet)

function LinkedList() {
    this.head = null;
    this.tail = null;
    this.length = 0;
}

Again: pure state.

The list object tracks:

No logic is embedded here. That comes next.

Adding Behavior via the Prototype

Behavior is shared by delegation, not copied per instance.

LinkedList.prototype.push = function (value) {
    var node = new LinkedListNode(value);
    if (!this.head) {
        this.head = node;
        this.tail = node;
    } else {
        this.tail.next = node;
        this.tail = node;
    }
    this.length++;
    return node;
};

What matters here is not the algorithm (which is straightforward), but the mechanics:

There is no class. There is an object that other objects consult.

Prepending: Same Structure, Different Traversal

LinkedList.prototype.prepend = function (value) {
    var node = new LinkedListNode(value);
    if (!this.head) {
        this.head = node;
        this.tail = node;
    } else {
        node.next = this.head;
        this.head = node;
    }
    this.length++;
    return node;
};

The list remains consistent because:

This reinforces an important lesson: structure emerges from references, not from containers.

Searching by Traversal

LinkedList.prototype.find = function (value) {
    var cur = this.head;
    while (cur) {
        if (cur.value === value) return cur;
        cur = cur.next;
    }
    return null;
};

Here we see object graphs in action:

This is prototype-based thinking at its clearest.

Removing a Node: Local Reasoning Only

LinkedList.prototype.remove = function (value) {
    var prev = null;
    var cur = this.head;
    while (cur) {
        if (cur.value === value) {
            if (prev) {
                prev.next = cur.next;
            } else {
                this.head = cur.next;
            }
            if (cur === this.tail) {
                this.tail = prev;
            }
            this.length--;
            return true;
        }
        prev = cur;
        cur = cur.next;
    }
    return false;
};

No global invariants. No superclass contracts.

Just:

This is object-oriented programming without ceremony.

Observation, Not Encapsulation

LinkedList.prototype.toArray = function () {
    var out = [];
    var cur = this.head;
    while (cur) {
        out.push(cur.value);
        cur = cur.next;
    }
    return out;
};

The list does not hide its internals behind layers of abstraction. Instead:

Nothing is implicit.

A Concrete Usage Example in ProtoScript

To conclude, here is a minimal but complete usage example written in ProtoScript. It shows how the data structure is consumed from user code, without any special syntax or runtime magic.

github.com/ppyne/ProtoScript

ProtoScript.include("LinkedList.js");

var list = new LinkedList();
list.push("b");
list.push("c");
list.prepend("a");

var found = list.find("b");
Io.print((found ? "found b" : "missing b") + Io.EOL);

list.remove("a");
Io.print("len=" + list.length + Io.EOL);

var values = list.toArray();
Io.print(values.join(",") + Io.EOL);

Several important observations can be made:

This example demonstrates that prototype-based OO scales naturally from definition to usage, without any change in mental model.

Why This Example Matters

This small program demonstrates, in one place:

Had this been shown early on, JavaScript would have been understood very differently.

Final Thought

Prototype-based OO is not a weaker form of class-based OO.

It is simpler, more explicit, and closer to how programs actually execute.

This linked list is not just a data structure.

It is a conceptual Rosetta Stone.

Alexandre Vialle

You may also like

JavaScript: A Name That Confused a Generation