How To Create Blog In C Corner
Introduction
JavaScript is filled with Objects! Although JavaScript doesn't have the "class" keyword as you might be familiar with in C#, it is nonetheless filled with objects. Upon deeper investigation you will find that JavaScript's native types are objects and that functions are first-class objects! This means that functions can be treated like objects.
In this mini-series we will be reviewing some of the various ways you can create objects in JavaScript
- The Constructor Pattern
- The Prototype Pattern
- The Constructor and Prototype Pattern
- The Object.create() Pattern
The Constructor Pattern
To begin we will start with the Constructor Pattern. This pattern should look most familiar to a C# developer and could quite possibly a technique that you may have already seen used in JavaScript.
Before we start writing some JavaScript, let's first define a simple C# Skillet class that we will later rewrite as a comparable JavaScript Constructor.
using System;</p> <p>public class Skillet { public string Ingredient { get; set; } public int Quantity { get; set; }</p> <pre><code>public Skillet( string ingredient, int quantity ) { this.Ingredient = ingredient; this.Quantity = quantity; } public void fry() { Console.WriteLine( &amp;amp;quot;Frying &amp;amp;quot; + this.Quantity + &amp;amp;quot; &amp;amp;quot; + this.Ingredient ); } </code></pre> <p>}</p> <p>public class Runner { public static void Main() { Skillet mySkillet = new Skillet( &amp;quot;bacon strips&amp;quot;, 2 ); mySkillet.fry(); } }
You can run the above code from ideone.
The above C# Skillet class has two properties (Ingredient and Quanity) and one method (fry). The sample code creates an instance of the Skillet, providing the ingredient and quanity in it's constructor, and then calls the fry method which prints out a message to the console.
Now that we have a simple C# example, let's now take that class and rewrite it using the JavaScript Constructor Pattern. We will attempt to stay as close to the C# code as possible and then later will come back and address some problems and limitations of this technique.
The first step of writing a JavaScript Constructor is to make a function that will represent the new type you are defining. You could think of this function similar to the concept of the C# "class" as seen in the above example. This function will serve as the blueprint of what your object will look like once it is created. Inside the Constructor we need to define the properties and functions that the object will have when created.
function Skillet( ingredient, quantity ) { this.ingredient = ingredient; this.quantity = quantity;</p> <pre><code>this.fry = function() { console.log( &amp;amp;quot;Frying &amp;amp;quot; + this.quantity + &amp;amp;quot; &amp;amp;quot; + this.ingredient ); }; </code></pre> <p>}</p> <p>var mySkillet = new Skillet( &amp;quot;bacon strips&amp;quot;, 2 );</p> <p>mySkillet.fry();
You can execute and modify the above code from jsFiddle.
Note: Towards the end of this article I will show how you could namespace this constructor, but I for now I will not to keep the examples focused on the topic at hand.
Other than some minor syntax differences, the C# and JavaScript examples look very similar.
There are some important things you should notice about the JavaScript Constructor Pattern above:
- It is considered best practice to capitalized the first letter of the function name to indicate that it is a Constructor. This is not necessary, but it is a practice that other JavaScript developers will recognize and appreciate.
- The functions and properties are assigned onto the "this" object
- There is no return statement for the Constructor
- You you the "new" operator to create the new instance. If you didn't use "new", then the "this" object would have referred to the global "window" object and all properties and functions would have been added to that.
Be Careful Where You Declare Your Functions
Although the JavaScript version of the Skillet outputs the same as the C# version, there is an issue that we need to resolve. When you "new" up an instance of the Skillet in JavaScript the constructor is actually creating new instances of the "fry" and "toString" functions as well. So, if you created multiple skillets they wouldn't be using the same function.
var baconSkillet = new Skillet( &amp;quot;bacon strips&amp;quot;, 4 ), eggsSkillet = new Skillet( &amp;quot;eggs&amp;quot;, 2 );</p> <p>console.log( baconSkillet.fry === eggsSkillet.fry ); //false
As you can see in the following diagram there are two instances of the fry function.
Note: I have intentionally left out some important pieces of this diagram as they will be address in the next article in this series when we discuss prototypes.
If you end up creating a lot of skillets this will end up taking much more memory than you intended, also if you ever wanted to update a function it would not reflect across all of the skillets.
In order to get around this problem, you can define the functions outside of the Constructor and then reference the functions instead.
function Skillet( ingredient, quantity ) { this.ingredient = ingredient; this.quantity = quantity;</p> <pre><code>this.fry = fry; this.toString = toString; </code></pre> <p>}</p> <p>function fry() { console.log( &amp;quot;Frying &amp;quot; + this.quantity + &amp;quot; &amp;quot; + this.ingredient ); }</p> <p>function toString() { console.log( this.quantity + &amp;quot; &amp;quot; + this.ingredient ); }</p> <p>var baconSkillet = new Skillet( &amp;quot;bacon strips&amp;quot;, 4 ), eggSkillet = new Skillet( &amp;quot;eggs&amp;quot;, 2 );</p> <p>console.log( baconSkillet.fry === eggSkillet.fry ); //true
By splitting out the fry function definition outside the constructor, the skillet instances all reference the same function as show in the following diagram.
Unfortuantely, this fragements the definition of your type, but it isn't too horrible.
Be Careful When Overridding Methods
Due to the dynamic nature of JavaScript, we can actually override one of the functions of an object at runtime, however, the override will only apply to that instance of the object.
var baconSkillet = new Skillet( &amp;quot;bacon strips&amp;quot;, 4 ), eggSkillet = new Skillet( &amp;quot;eggs&amp;quot;, 2 );</p> <p>eggSkillet.fry = function() { console.log( &amp;quot;Cooking &amp;quot; + this.quantity + &amp;quot; &amp;quot; + this.ingredient ); };</p> <p>baconSkillet.fry(); //Frying 4 bacon strips</p> <p>eggSkillet.fry(); //Cooking 2 eggs
As the diagram below shows, the overridden fry function only applies to the mySkillet2 object. The mySkillet1 object still refernces the function set when it was created.
Protect Your Constructor From The Window
As we've mentioned before, it is important to use the "new" operator when using the Constructor Patter, otherwise the properties and method will be applied off of the window and not a new object as you intended. In order to protect against this, you could first check in your constructor that the context is indeed the Skillet and not something else. If for some reason a developer forgets to use the "new" operator, you can manually use the "new" operator when using your constructor to get the desired behavior.
function Skillet( ingredient, quantity ) { //Protect against someone not using &amp;quot;new&amp;quot; operator if ( this instanceof Skillet ) { this.ingredient = ingredient; this.quantity = quantity;</p> <pre><code> this.fry = fry; this.toString = toString; } else { return new Skillet( ingredient, quantity ); } </code></pre> <p>}</p> <p>function fry() { console.log( &amp;quot;Frying &amp;quot; + this.quantity + &amp;quot; &amp;quot; + this.ingredient ); }</p> <p>function toString() { console.log( this.quantity + &amp;quot; &amp;quot; + this.ingredient ); }</p> <p>//Developer forgot to use &amp;quot;new&amp;quot; operator on mySkillet1 var Skillet1 = Skillet( &amp;quot;bacon strips&amp;quot;, 4 ), mySkillet2 = new Skillet( &amp;quot;eggs&amp;quot;, 2 );</p> <p>console.log( window.ingredient ); //undefined</p> <p>console.log( mySkillet1.ingredient ); //bacon strips</p> <p>console.log( mySkillet2.ingredient ); //eggs
The above code snippet works just the same regardless whether the developer uses the "new" operator or not. You may or may not feel this is necessary, but if you need the protection it is available using this technique.
How to Namespace Your Constructor
Before we finish talking about Constructors, I wanted to breifly talk about how you could namespace them. All of my examples thus far were not namespaced mainly because I wanted to focus on the technique of the pattern and not clutter it up with extra syntax. However, in your project it is a good idea to namespace your work for the benefit of yourself and others.
(function(kitchen, undefined) {</p> <pre><code>kitchen.Skillet = function(ingredient, quantity) { this.ingredient = ingredient; this.quantity = quantity; this.fry = fry; } function fry() { console.log(&amp;amp;quot;Frying &amp;amp;quot; + this.quantity + &amp;amp;quot; &amp;amp;quot; + this.ingredient); } var mySkillet1 = new kitchen.Skillet(&amp;amp;quot;bacon strips&amp;amp;quot;, 4), mySkillet2 = new kitchen.Skillet(&amp;amp;quot;eggs&amp;amp;quot;, 2); console.log(mySkillet1.fry === mySkillet2.fry); //true console.log(mySkillet1 instanceof kitchen.Skillet); //true </code></pre> <p>})( window.kitchen = window.kitchen || {} );
The main difference of this code example versus the previous examples is that I am wrapping all of the code in a self-executing anonymous function and passing in a variable that should be used as the namespace. Since the constructor is attached to the namespace you will need to provide the full namespace when creating a new instance of it or when using the 'instanceof' operator as shown above in the code snippet.
Pros of This Technique
- The Constructor Pattern is a familiar concept to a C# developer
- The syntax of the constructor is similar to that of a C# class
- There is a technique to protect against developers that don't use the "new" operator
Cons of This Technique
- You need to be care not to declare your functions in your constructor
- If you declare your functions outside the constructor, then the object definition is no longer all in one place.
- If you decided to change the behavior of one of the object's functions, it would apply only to that object and not all instances.
Conclusion
The Constructor pattern is probably one of the most familar looking to a C# developer. You will most likely run into this pattern when searching around on the internet. You should be familiar with this pattern and know it's strengths and weaknesses as we pointed out in this article.
In the next section we are going to introduce the concept of the JavaScript Prototype, which will help address some of these issues brought up in this article.
How To Create Blog In C Corner
Source: https://www.developintelligence.com/blog/2015/03/c-corner-creating-javascript-objects-part-1-constructor/
Posted by: mcculloughhimper.blogspot.com
0 Response to "How To Create Blog In C Corner"
Post a Comment