Defining Prototypes in JavaScript
- JavaScript is an object-based language based on prototypes
- JavaScript isn't class-based for creating and managing its objects
- A prototype-based language does not make the distinction between classes and instances
- Instead, it just simply has objects
Properties of Prototype-based JavaScript
- All objects can inherit from another object
- Classes and instances are distinct entities
- Prototypes define and create a set of objects with constructor functions
- Objects are created using the
new
operator - A resulting object hierarchy is constructed by assigning an objects as the prototype associated with a constructor function
- Objects inherit properties by following the prototype chain
-
An initial set of properties is specified by either:
- A constructor function
- A prototype
-
Properties can be added and removed dynamically to individual objects
- They can also be added to an entire set of objects dynamically
- Objects just see a prototype as property
Creating Objects with Constructors
- By convention, constructors are meant to be capitalized functions
- Constructors are called with the
new
operator to create an object -
Calling
new Constructor()
does the following:- Creates a new object
- Assigns the object to the
this
value in the constructor - Reserves the
prototype
property for internal use -
The new object is implicitly returned by the constructor
- This is why constructors don't have return statements
-
Anything defined in the constructor's prototype becomes available to instances
- Specifically, by calling the
new
operator on the constructor
- Specifically, by calling the
- Assigning properties in a constructor will create a global variable
Illustrating Object Creation with Constructors
// constructor function
function Person() {
this.a = function() { return 'a' };
}
Person.prototype.b = function() { return 'b' };
Person.c = function() { return 'c' };
var test = new Person(); // person object
test.a(); // works
test.b(); // works
test.c(); // error
test.prototype.b(); // error
Use Cases for Constructors
-
Define properties in constructors when:
- Defining properties based on arguments of constructor function
- Defining public methods with access to private variables
-
Define methods on the prototype property when:
- Defining dynamic methods and properties based on arguments from constructor function
-
Needing better performance
- Each method has to be created every time the constructor function runs
- Methods on the prototype chain are created once and then inherited by each instance
Illustrating Use Cases for Constructors
// Properties defined within constructor
// based on arguments
function Person(a, b) {
this.a = a;
this.b = b;
}
// Methods defined within constructor
// using private variables
function Person(name) {
let prefix = 'hello ';
this.a = prefix + a;
this.b = function() { return prefix + a };
}
// Methods defined in prototype
// for dynamic functions
function Person(a, b) {
this.a = a;
this.b = b;
}
Person.prototype.c = function() { return a+b };
Illustrating Comparison of Constructors and Prototypes
// Accessing constructor from object instances
obj1.constructor === Object // true
obj2.constructor === SomeConstructor // true
// Accessing prototype from object instances
// ...with a Constructor
mike.__proto__ === Person.prototype // true
mike.__proto__.__proto__ === Object.prototype // true
// ...and with a Factory
mike.__proto__ === Object.Prototype // true
References
Next