User Tools

Site Tools


javascript:prototypes:the_prototype

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
javascript:prototypes:the_prototype [2018/08/10 22:26] – created mithatjavascript:prototypes:the_prototype [2018/08/10 23:15] (current) – [The JavaScript Prototype] mithat
Line 1: Line 1:
-====== The Prototype ======+====== The JavaScript Prototype ======
  
-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 intended as a gentle guide through the realm of JavaScript prototypes. If youre 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.
  
 ===== Context and Motivations ===== ===== Context and Motivations =====
  
-You probably know how to create an object literal -- say for a person:+You probably know how to create an object literal – say for a person:
  
 <code javascript> <code javascript>
Line 16: Line 16:
 }; };
 </code> </code>
- 
 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('Athena'); var athena = makePerson('Athena');
 </code> </code>
- 
 or a constructor function: or a constructor function:
  
Line 48: Line 46:
 var athena = new Person('Athena'); var athena = new Person('Athena');
 </code> </code>
 +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’t it be nice if there was a convenient place where we could put shared stuff like this and only refer to that one copy instead of making each object carry around its own copy? This could save a lot of memory if there are a lot of Persons or if a shared property happens to be really big.
  
-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't it be nice if there was a convenient place where we could put shared stuff like this and only refer to that one copy instead of making each object carry around its own copy? This could save a lot of memory if there are a lot of Persons or if a shared property happens to be really big. +Also, what if we want to create a kind of Person that, say, is a bit more specialized – like a Teacher. A teacher might be identical to a Person except that they have an additional ''%%subject%%'' property and a ''%%saySubject%%'' method. Wouldnt it be nice if we could just specify how a Teacher is special in relation to a Person rather than copy/paste the code we already wrote for Person?
- +
-Also, what if we want to create a kind of Person that, say, is a bit more specialized -- like a Teacher. A teacher might be identical to a Person except that they have an additional `subjectproperty and a `saySubjectmethod. Wouldn't it be nice if we could just specify how a Teacher is special in relation to a Person rather than copy/paste the code we already wrote for Person?+
  
 ===== Enter the Prototype ===== ===== Enter the Prototype =====
  
-JavaScript offers a solution to both of these via the **prototype**. Every _function_ in JavaScript automatically gets a special property attached to it called `prototype`: +JavaScript offers a solution to both of these via the **prototype**. Every //function// in JavaScript automatically gets a special property attached to it called ''%%prototype%%'':
  
 +<code javascript>
 function bar () { function bar () {
 }; };
 console.log(bar.prototype); console.log(bar.prototype);
 +</code>
 +A ''%%prototype%%'' is an object with a bunch of properties, including, curiously, one called ''%%constructor%%'' that points back to the function itself.
  
- 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("That's cute.");   console.log("That's cute.");
Line 69: Line 67:
   console.log('You lied.');   console.log('You lied.');
 }; };
 +</code>
 +Going further, when you instantiate an //object// it will automatically recieve a property called ''%%__proto__%%'' that is a reference to its constructor’s ''%%prototype%%''. ((The use of the ''%%__proto__%%'' identifier for this function appears to be true of browsers. In Node.js it might be different.))
  
- Going further, when you instantiate an _object_ it will automatically recieve a property called `__proto__` that is a reference to its constructor's `prototype`.((The use of the `__proto__` identifier for this is true of broswers; in Node.js it might be different.))  +<code javascript>
- +
 function Person(name) { function Person(name) {
   this.name = name;   this.name = name;
Line 88: Line 86:
   console.log('You lied.');   console.log('You lied.');
 }; };
 +</code>
 +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 ''%%__proto__%%'' (i.e., the constructor’s ''%%prototype%%'') for it.
  
- Even further, 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 `__proto__` (i.e., the constructor's prototype) for it. +Lets set a property on ''%%Person.prototype%%'' and see what happens:
- +
-Let's set a property in `Person.prototypeand see what happens: */+
  
 +<code javascript>
 Person.prototype.deepDarkSecret = "I descended from apes." Person.prototype.deepDarkSecret = "I descended from apes."
  
Line 100: Line 99:
   console.log('No secrets.')   console.log('No secrets.')
 } }
 +</code>
 +No secrets.
  
- No secrets. */ +<code javascript>
 console.log( fuzz.deepDarkSecret ); console.log( fuzz.deepDarkSecret );
 +</code>
 +Oops!
  
- Oops! +The ''%%deepDarkSecret%%'' is actually a property in ''%%Person.prototype%%'', a.k.a., ''%%fuzz.__proto__%%''.
- +
-The `deepDarkSecretis actually a property in `Person.prototype`, a.k.a., `fuzz.__proto__`*/+
  
 +<code javascript>
 if (fuzz.deepDarkSecret === fuzz.__proto__.deepDarkSecret) { if (fuzz.deepDarkSecret === fuzz.__proto__.deepDarkSecret) {
   console.log("That's cute.");   console.log("That's cute.");
Line 114: Line 115:
   console.log('You lied.');   console.log('You lied.');
 }; };
 +</code>
 +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"); athena = new Person("Athena");
 console.log(athena.deepDarkSecret); console.log(athena.deepDarkSecret);
 +</code>
  
- ## Not just a cute party trick+===== 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''%%prototype%%'' is a convenient place to stuff the properties of objects made with it whose values are common to all objects. Most methods fit into this category as well as potentially other properties:
- */+
  
 +<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();
 +</code>
 +''%%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’s ''%%prototype%%'' – and it finds it there.
  
- +<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's `prototype` -- and it finds it there. +
- +
 if (fuzz.name !== athena.name) { if (fuzz.name !== athena.name) {
   console.log("That's what I expeceted.")   console.log("That's what I expeceted.")
Line 164: Line 164:
   console.log("You lied.")   console.log("You lied.")
 } }
 +</code>
 +[[#|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

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki