javascript:prototypes:the_prototype
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
javascript:prototypes:the_prototype [2018/08/10 22:26] – created mithat | javascript:prototypes:the_prototype [2018/08/10 23:15] (current) – [The JavaScript Prototype] mithat | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== The Prototype ====== | + | ====== The JavaScript |
- | This is intended as a gentle guide through the realm of JavaScript prototypes. If you're coming here from a class-based language like Java, PHP, C#, or C++ I suggest you put aside everything you know about how objects and inheritance work in those languages. Try to treat the way JavaScript works as its OwnThing. | + | This is the first in a series of articles |
===== Context and Motivations ===== | ===== Context and Motivations ===== | ||
- | You probably know how to create an object literal | + | You probably know how to create an object literal |
<code javascript> | <code javascript> | ||
Line 16: | Line 16: | ||
}; | }; | ||
</ | </ | ||
- | |||
This works fine for one-off objects. If you need to create more than one person, you could create a factory function: | This works fine for one-off objects. If you need to create more than one person, you could create a factory function: | ||
Line 33: | Line 32: | ||
var athena = makePerson(' | var athena = makePerson(' | ||
</ | </ | ||
- | |||
or a constructor function: | or a constructor function: | ||
Line 48: | Line 46: | ||
var athena = new Person(' | var athena = new Person(' | ||
</ | </ | ||
+ | In both of the above, '' | ||
- | In both of the above, `fuzz` and `athena` each have their very own copies of `name`, `greeting`, and `sayName`. For a small set of small objects, this is fine. But consider that every Person so defined has properties whose values are common to all Persons (`sayName` and, arguably, `greeting`). Wouldn' | + | Also, what if we want to create a kind of Person that, say, is a bit more specialized |
- | + | ||
- | Also, what if we want to create a kind of Person that, say, is a bit more specialized | + | |
===== Enter the Prototype ===== | ===== Enter the Prototype ===== | ||
- | JavaScript offers a solution to both of these via the **prototype**. Every _function_ | + | JavaScript offers a solution to both of these via the **prototype**. Every // |
+ | <code javascript> | ||
function bar () { | function bar () { | ||
}; | }; | ||
console.log(bar.prototype); | console.log(bar.prototype); | ||
+ | </ | ||
+ | A '' | ||
- | A `prototype` is an object with a bunch of properties, including, curiously, one called `constructor` that points back to the function itself. */ | + | <code javascript> |
if (bar.prototype.constructor === bar) { | if (bar.prototype.constructor === bar) { | ||
console.log(" | console.log(" | ||
Line 69: | Line 67: | ||
console.log(' | console.log(' | ||
}; | }; | ||
+ | </ | ||
+ | Going further, when you instantiate an //object// it will automatically recieve a property called '' | ||
- | Going further, when you instantiate an _object_ it will automatically recieve a property called `__proto__` that is a reference to its constructor' | + | <code javascript> |
- | + | ||
function Person(name) { | function Person(name) { | ||
this.name = name; | this.name = name; | ||
Line 88: | Line 86: | ||
console.log(' | console.log(' | ||
}; | }; | ||
+ | </ | ||
+ | If you try to access an object’s property, the JavaScript engine will first look in the object itself for it; if it doesn’t find it there, it will look in '' | ||
- | Even further, if you try to access an object' | + | Let’s set a property |
- | + | ||
- | Let's set a property | + | |
+ | <code javascript> | ||
Person.prototype.deepDarkSecret = "I descended from apes." | Person.prototype.deepDarkSecret = "I descended from apes." | ||
Line 100: | Line 99: | ||
console.log(' | console.log(' | ||
} | } | ||
+ | </ | ||
+ | No secrets. | ||
- | No secrets. */ | + | <code javascript> |
console.log( fuzz.deepDarkSecret ); | console.log( fuzz.deepDarkSecret ); | ||
+ | </ | ||
+ | Oops! | ||
- | | + | The '' |
- | + | ||
- | The `deepDarkSecret` is actually a property in `Person.prototype`, a.k.a., | + | |
+ | <code javascript> | ||
if (fuzz.deepDarkSecret === fuzz.__proto__.deepDarkSecret) { | if (fuzz.deepDarkSecret === fuzz.__proto__.deepDarkSecret) { | ||
console.log(" | console.log(" | ||
Line 114: | Line 115: | ||
console.log(' | console.log(' | ||
}; | }; | ||
+ | </ | ||
+ | And when we added it to the prototype, it became available to all instances of Person. | ||
- | And when we added it to the prototype, it became available to all instances of Person. | + | <code javascript> |
- | + | ||
athena = new Person(" | athena = new Person(" | ||
console.log(athena.deepDarkSecret); | console.log(athena.deepDarkSecret); | ||
+ | </ | ||
- | ## | + | ===== Not just a cute party trick ===== |
- | The upshot of this is that a constructor's prototype is a convenient place to stuff the properties of objects made with it that whose values are common to all objects: | + | The upshot of this is that a constructor’s '' |
- | */ | + | |
+ | <code javascript> | ||
function Person(name) { | function Person(name) { | ||
this.name = name; | this.name = name; | ||
Line 139: | Line 141: | ||
fuzz.sayName(); | fuzz.sayName(); | ||
athena.sayName(); | athena.sayName(); | ||
+ | </ | ||
+ | '' | ||
+ | When you ask '' | ||
- | + | <code javascript> | |
- | fuzz and athena now each have their own `name` properties. However, they are using the common `greeting` and `sayName` properties, saving the memory it would have required for them to have their own copies of those. | + | |
- | + | ||
- | When you ask athena to say her name, the JavaScript engine first looks for the `sayName` identifier in the `athena` object. But it won't find it there. So the next place it looks is `athena.__proto__` -- which is the constructor' | + | |
- | + | ||
if (fuzz.name !== athena.name) { | if (fuzz.name !== athena.name) { | ||
console.log(" | console.log(" | ||
Line 164: | Line 164: | ||
console.log(" | console.log(" | ||
} | } | ||
+ | </ | ||
+ | [[#|Next]] we’ll have a look at what happens when you manipulate properties you’ve set on prototypes. | ||
- | Next we'll have a look at what happens when you manipulate properties you've set on prototypes. */ |
javascript/prototypes/the_prototype.1533939967.txt.gz · Last modified: 2018/08/10 22:26 by mithat