JavaScript Prototypes and Inheritance June 10th, 2014
Objects have a built-in attribute called prototype who’s value is a pointer to another object, and can be declared when creating a new object with Object.create(myPrototypeReference). If an object is created using the convenience of an object literal var newObject = {property: ‘value‘} then the prototype is defaulted to Object.prototype.
Overview
- Objects are pairs of keys and values called properties (in Ruby, this structure is called a Hash; in Python, it’s called a dictionary)
- Properties can be enumerable, configurable, and writable
- Objects have a built-in attribute called prototype who’s value is a pointer to another object
- Specify an object’s prototype by using Object.create(prototype) when creating the new object
- If you don’t need a prototype then you can use the convenience of the object literal syntax instead … var newObject = {property: ‘value‘} … which always set the newly created object’s prototype to an object located at Object.prototype
- You can look up an object’s prototype by using Object.getPrototypeOf(object)
- Define new properties with Object.defineProperty(object, ‘newKey’, {value:‘New Key Value’, writable:true, enumerable:true, configurable:true})
- Since creating a new writable, configurable, enumerable property is pretty common, JavaScript makes it easy to do so using assignment syntax instead … object.newKey = ‘newValue’
- Prototypes can be used to inherit functionality
- If you try to look up a key on an object and it is not found, JavaScript will look for it in the prototype. It will follow the “prototype chain” until it sees a null value. In that case, it returns undefined.
Prototypal Inheritance Analogy
var defaults = {
zero: 0,
one: 1
};
var myOptions = Object.create(defaults);
var yourOptions = Object.create(defaults);
// When I want to change *just* my options
myOptions.zero = 1000;
// When you wanna change yours
yourOptions.one = 42;
// When we wanna change the **defaults** even after we've got our options
// even **AFTER** we've already created our instances
defaults.two = 2;
myOptions.two; // 2
yourOptions.two; // 2