Internal and external prototype

ECMAScript has two different prototype concepts which can be confusing:

"Internal prototype" and "external prototype" are not standard terms, but used in Duktape documentation for clarity.

See also:

Internal prototype

The internal prototype, also referred to simply as "prototype", is specified as the internal property [[Prototype]] in the ECMAScript specification:

It affects actual property lookups such as obj.prop. To simplify a bit, a property lookup:

Being an internal property, the [[Prototype]] property is not directly accessible, but it can be interacted with using:

The ECMAScript APIs (__proto__ and Obj.setPrototypeOf) prevent creation of prototype loops; an attempt to create one fails with a TypeError:

duk> var obj1 = {}; var obj2 = {};
= undefined
duk> Object.setPrototypeOf(obj1, obj2); Object.setPrototypeOf(obj2, obj1);
TypeError: type error (rc -105)
    setPrototypeOf  native strict preventsyield
    global input:1 preventsyield

However, the Duktape C API is lower level and allows you to create a prototype loop (which should generally be avoided). Duktape has sanity limits to terminate lookups from looped prototype chains.

External prototype

The external prototype is the .prototype property present in most ECMAScript functions. It's present in all functions by default, but can be removed manually (also some built-ins don't have the property). The .prototype property only has an effect when a function is called as a constructor, i.e.:

var obj = new MyConstructor();

When the constructor call happens (see for details):

The only point where the external prototype has an effect is in initializing the default instance. In particular, if you ignore the default instance and explicitly return an object value from the constructor, the external prototype has no effect on the objects created.

Default external prototype object of ECMAScript functions

When you declare a function in ECMAScript code the ECMAScript semantics provide an automatic external .prototype object. For example, when declaring:

function MyConstructor() {
    // ...

the following objects are automatically created:

The prototype object is empty except for a .constructor property which points back to the constructor function, so that:

MyConstructor.prototype.constructor === MyConstructor

The internal prototype of MyConstructor.prototype is Object.prototype so that when properties are looked up from objects created using new MyConstructor(), the prototype chain is by default:

For simple objects a common idiom is for inherited methods to be added to MyConstructor.prototype.

There are many ways to control the eventual prototype chain of instance objects:

No default external prototype object for Duktape/C functions

Duktape/C functions behave identically to ECMAScript functions when called as constructors: a default instance is created based on the .prototype property of the Duktape/C function, etc.

However, to minimize memory usage, Duktape/C functions don't have an external prototype (.prototype property) by default. This means that the default instance will inherit from Object.prototype unless you:

See: How to write a native constructor function.