By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,402 Members | 1,107 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,402 IT Pros & Developers. It's quick & easy.

JavaScript Object and Prototypes

Frinavale
Expert Mod 5K+
P: 9,731
JavaScript is a very strange place for me...

So, I decided that, before I attempt to create an Object, I should first learn about Objects. I had actually created one before with the help of a tutorial. The tutorial was complicated because showed me how to create a JavaScript Object that is a representation my .NET Object and how to get the two to "work together as one".... apparently the tutorial was not very clear about what was going on in the JavaScript Object...and even with my extensive commenting of the JavaScript Object I still didn't "really" know what was going on...at the time I was more interested in the .NET concepts than the JavaScript techniques being used in the tutorial.

Anyways, I started with the basics: how do I create a JavaScript Object.
To my surprise all functions were Objects, all Objects were Functions and I was not pleased with this new way of thinking because it's really strange...but it's just how things are.

The next thing I did was try to figure out what I had done to create the JavaScript Object in the tutorial. This Object uses the prototype property (which is apparently an Object and is a property of all functions) to add functions and properties to the Object.

So I started playing around with a silly little (uncomplicated) Object of my own...

Please see the comments in the following code for what I'm confused about:

Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <body>
  3.  
  4. <script type="text/javascript">
  5.  
  6. /*Welcome to my little Foo Class experimentation.
  7. The following function is a "constructor function", 
  8. that will create an instance of my Foo Object*/
  9. function Foo(firstNumber,secondNumber){
  10.   this.a = firstNumber; //"a" is now a property of the Foo Object
  11.   this.b = secondNumber;//"b" is now a property of the Foo Object
  12.   this.Multiply = function(){return this.a * this.b;}//Multiply is now a method for my Foo Object
  13.   this.Divide = function(){return "you're in Foo's Divide function";}
  14.   //The Divide method is NOT overwritten by the Divide method in the prototype Object
  15.  
  16. /*
  17. The following does not work.
  18. Even though it does work when I use the same sort of 
  19. thing to "overwrite" the prototype Object.
  20.  
  21. Why??
  22. */
  23.  
  24.   /*a: firstNumber,
  25.   b: secondNumber,
  26.   Multiply: function(){return this.a * this.b;}*/
  27. };
  28.  
  29. //This was my first experiment:
  30. //I used the prototype property to add the Divide method to the Foo Class
  31. /*Foo.prototype.Divide = function(){return this.a/this.b;};*/
  32.  
  33. //This is my second experiment:
  34. //overwrite the prototype Object
  35. //This works fine but...
  36. //What is with the colons (:) and commas (,)??
  37. //I don't get it
  38. Foo.prototype = {
  39.     Add: function(){return this.a + this.b},
  40.     Divide: function(){return this.a/this.b;}
  41. };
  42.  
  43. var instanceOfFoo = new Foo(2,3);
  44.  
  45. //JavaScript couldn't find Add in the Foo class
  46. //it looks to the prototype Object and finds it there
  47. document.write(instanceOfFoo.Add());
  48. document.write("<br />");
  49. document.write(instanceOfFoo.Multiply());
  50. document.write("<br />");
  51.  
  52. //The Divide method is found in the Foo class and is used 
  53. //instead of the one defined in the prototype
  54. document.write(instanceOfFoo.Divide());
  55. document.write("<br />");
  56.  
  57. //The following doesn't work...
  58. //how do you access the Divide method in the prototype???
  59. //document.write(instanceOfFoo.prototype.Divide());
  60. //document.write("<br />");
  61. document.write("<br />");
  62.  
  63.  
  64. var anotherInstanceOfFoo = new Foo(10,2);
  65. document.write(anotherInstanceOfFoo.Add());
  66. document.write("<br />");
  67. document.write(anotherInstanceOfFoo.Multiply());
  68. document.write("<br />");
  69. document.write(anotherInstanceOfFoo.Divide());
  70. document.write("<br />");
  71. document.write("<br />");
  72.  
  73. instanceOfFoo.newProperty = "instanceOfFoo's property";//adds a property named "newProperty" to the instanceOfFoo live Object.
  74. document.write(instanceOfFoo.newProperty);
  75. document.write("<br />");
  76. document.write(anotherInstanceOfFoo.newProperty);//is undefined because it is only available to the instanceOfFoo live Object
  77. document.write("<br />");
  78. document.write("<br />");
  79.  
  80. //Adding a property named "newProperty" to the prototype object of the Foo class
  81. //This makes it available to all instances of the Foo class (live ones too) 
  82. Foo.prototype.newProperty ="newly added property to prototype which is available to all 
  83. instances of Foo.";
  84.  
  85. //It's interesting that the original value for the "newProperty" property is kept
  86. document.write(instanceOfFoo.newProperty);
  87. document.write("<br />");
  88. document.write(anotherInstanceOfFoo.newProperty);//now contains a value
  89. document.write("<br />");
  90.  
  91. </script>
  92.  
  93. </body>
  94. </html>

Thanks for your help clarifying the questions in the above posted code!

-Frinny
Feb 20 '09 #1
Share this Question
Share on Google+
23 Replies


gits
Expert Mod 5K+
P: 5,387
ok .... let's have a closer look at it :) ...

typically you create a constructor like this:

Expand|Select|Wrap|Line Numbers
  1. function MY_OBJ() {
  2.     this.prop = 'foo';
  3.     this.func = function() { //whatever code };
  4. }
  5.  
  6. // use the constructor
  7. var my_obj = new MY_OBJ;
  8.  
you cannot mix that with the : notation of properties ... the properties are declared with this.prop in the above case, and need explicit assignments.

Now you could even create a new object like this literally:

Expand|Select|Wrap|Line Numbers
  1. var foo = {
  2.     a: 'some_value',
  3.     b: function() { // whatever code }
  4. };
  5.  
here you create an instance of an object directly and you declare the properties a and b ... where b stores a reference to the function-code that is assigned to it. note: when you have a look at this ... this is where JSON is not far away ;) just have that as a string from a response and eval it and you have a native js-object ready for use.

so when you do:

Expand|Select|Wrap|Line Numbers
  1. some_obj.prototype = {
  2.     // whatever 
  3. };
  4.  
you create a new prototype-obj with the properties/methods you want the some_obj to have.

the 'classical' way to do that is:

Expand|Select|Wrap|Line Numbers
  1. some_obj.prototype.my_new_function = function() {
  2.     // function's code
  3. }
  4.  
so you just extend the prototype of the obj with just one property/method instead of overwriting the entire prototype. now you are asking how to call a method ... this is quite simple. when you have an instance you just call it like this:

Expand|Select|Wrap|Line Numbers
  1. obj_instance.method_name();
when you want to use the method without an instance, then just use:

Expand|Select|Wrap|Line Numbers
  1. constructor_name.prototype.method_name();
i hope this helps you? :)

kind regards

PS: be aware of the use of the this keyword when working with javascript object ... this always relates to the caller of a function ... so that might be tricky when starting to use objects in JavaScript.
Feb 20 '09 #2

Frinavale
Expert Mod 5K+
P: 9,731
@gits
What is the name of the ":" notation so that I can look this up?

@gits
Ok, "overwriting" makes sense to me now, thanks.

@gits
This is not exactly what I was asking.

I've defined 2 versions of the Divide() method: one in the Foo class and the other is in Foo's prototype.

The Divide() method in the Foo class simply returns a String stating that "you're in Foo's Divide function".

The Divide() method in Foo's prototype divides "a" property by "b" property.

I'm wondering how to call the Divide() method in the prototype for a live instance of Foo.....not how to statically call the Divide() method in the prototype...I don't know if I'm being clear here so if you don't understand my question I can try and restate it.
Feb 20 '09 #3

gits
Expert Mod 5K+
P: 5,387
the prototype is first parsed and later when you create the instance then the member-variables are allocated. when you have a prototype-property for the obj and then create a member directly this will drop the reference to the prototypes method for this obj. so the member will 'override' the prototype for this instance ... you only could call it staticly

using the prototype is to prefer because members will always alloc memory while the prototype is read and parsed only once.

kind regards
Feb 20 '09 #4

gits
Expert Mod 5K+
P: 5,387
ahh ... and i don't know whether there is a name for the : - notation ... it could only be used when you create JavaScript-objects through the literals {}:

Expand|Select|Wrap|Line Numbers
  1. var a = {};
  2.  
  3. // is equivalent to:
  4.  
  5. var a = new Object;
kind regards
Feb 20 '09 #5

Frinavale
Expert Mod 5K+
P: 9,731
@gits
Ok I didn't know this. In fact I had a completely different view on this. I thought that the JavaScript engine would fist search the Object for the property/method and if it couldn't find it it would then search the prototype....

I thought the reason for why I couldn't get to the prototype's method was because the JavaScript engine found the method in the Object and simply used that method.

Are you saying that if there is a method defined in the Object, that there is no possible way to access a method with the same name in the prototype because it's being overwritten?

This honestly seems a bit backwards to me....I was thinking that I could use the prototype object to "extend" functionality of existing objects....but if I can't overwrite the existing methods then this idea obviously wont work.

This is disappointing
@gits
This will let allow for extended functionality on existing methods/properties as well...?? (testing)
Feb 20 '09 #6

gits
Expert Mod 5K+
P: 5,387
not exactly ... it is the following way:

1. script is loaded and parsed ... so even all prototypes are parsed for the classes first - all prototype-props become part of this for the constructor
2. now you create an instance -> the constructor is executed ... and the new function is assigned to the name that first had a reference to the prototypes method.

to overwrite you have to create a instance first and then overwrite the method for that instance or make use of inheritance and use different classes:

Expand|Select|Wrap|Line Numbers
  1. function FOO() {}
  2.  
  3. FOO.prototype.my_func = function() {};
  4.  
  5. function CHILD_FOO() {}
  6.  
  7. CHILD_FOO.prototype = new FOO;
  8.  
  9. CHILD_FOO.prototype.constructor = CHILD_FOO;
  10.  
  11. CHILD_FOO.prototype.my_func = function() {};
  12.  
  13. var child_foo = new CHILD_FOO;
  14.  
Feb 20 '09 #7

Frinavale
Expert Mod 5K+
P: 9,731
I'll try your example in a sec...

But this is working:
Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <body>
  3.  
  4. <script type="text/javascript">
  5.  
  6. function Foo(firstNumber,secondNumber){
  7.   this.a = firstNumber; //"a" is now a property of the Foo Object
  8.   this.b = secondNumber;//"b" is now a property of the Foo Object
  9. };
  10. Foo.prototype = {
  11.     Add: function(){return this.a + this.b;},
  12.     Divide: function(){return this.a/this.b;},
  13.     Multiply: function(){return this.a * this.b;}
  14. };
  15.  
  16. function GrownUpFoo(firstNumber, secondNumber, thirdNumber){
  17.    this.Foo = new Foo(firstNumber, secondNumber);
  18.    this.c = thirdNumber;
  19. };
  20.  
  21. GrownUpFoo.prototype = {
  22.      Multiply: function(){return this.Foo.a * this.Foo.b * this.c;}
  23. };
  24.  
  25.  
  26. var instanceOfGrownUpFoo = new GrownUpFoo(2,3,4);
  27. document.write(instanceOfGrownUpFoo.Multiply());
  28. document.write("<br />");
  29. document.write(instanceOfGrownUpFoo.Foo.Multiply());
  30.  
  31. </script>
  32.  
  33. </body>
  34. </html>
Feb 20 '09 #8

Frinavale
Expert Mod 5K+
P: 9,731
@gits
Ok that's basically what I did in my experiment.
This method also allows me to overwrite the method defined in the "class" function of the base...
Expand|Select|Wrap|Line Numbers
  1. <html>
  2. <body>
  3.  
  4. <script type="text/javascript">
  5.  
  6. function Foo(firstNumber,secondNumber){
  7.   this.a = firstNumber; //"a" is now a property of the Foo Object
  8.   this.b = secondNumber;//"b" is now a property of the Foo Object
  9.   this.Multiply = function(){return this.a * this.b;};
  10. };
  11. Foo.prototype = {
  12.     Add: function(){return this.a + this.b;},
  13.     Divide: function(){return this.a/this.b;},
  14. };
  15.  
  16. function GrownUpFoo(firstNumber, secondNumber, thirdNumber){
  17.    this.Foo = new Foo(firstNumber, secondNumber);
  18.    this.c = thirdNumber;
  19. };
  20.  
  21. GrownUpFoo.prototype = {
  22. //The following agumetns the multiply method
  23.      Multiply: function(){return this.Foo.Multiply() * this.c;}
  24. };
  25.  
  26.  
  27. var instanceOfGrownUpFoo = new GrownUpFoo(2,3,4);
  28. document.write(instanceOfGrownUpFoo.Multiply());
  29. document.write("<br />");
  30. document.write(instanceOfGrownUpFoo.Foo.Multiply());
  31.  
  32. </script>
  33.  
  34. </body>
  35. </html>
Feb 20 '09 #9

Frinavale
Expert Mod 5K+
P: 9,731
Thanks a lot for your help Gits!
I have a much better understand about the JavaScript engine, JavaScript Objects, and even inheritance in JavaScript.

:)

-Frinny
Feb 20 '09 #10

Frinavale
Expert Mod 5K+
P: 9,731
Just to recap everything I learned here:

There are 2 ways to define and use a class in JavaScript.
The fist allows you to define a class and use it to create multiple instances (objects) of it.

The other defines a class and creates an instance of it at the same time (literally) but cannot be used to create more instances of the class..

To create a class that you can create multiple instances of you need to define it like:
Expand|Select|Wrap|Line Numbers
  1.  function MY_CLASS() {
  2.     this.aProperty = 'foo';
  3.     this.aFunction = function() { return "something"; };
  4. }
Then you can use it to create multiple instances:
Expand|Select|Wrap|Line Numbers
  1. var firstMyClassInstance = new MY_CLASS();
  2. var secondMyClassInstance = new MY_CLASS();
  3. var thirdMyClassInstance = new MY_CLASS();
If you don't need to more than one instance of the class, you can define one and create an instance of it at the same time by:
Expand|Select|Wrap|Line Numbers
  1. //the variable anObject is an object that is an instance of the class defined inline/litterally
  2. var anObject= {
  3.     aProperty: 'some_value',
  4.     aFunction: function() { return "something";}
  5. };
Also the prototype property is an Object that is part of every Object.
It is used to provide additional properties/methods to an Object but is not to be used to "overwrite" any properties/methods in the class that is a part of. The JavaScript engine loads and parses the prototype Object and anything defined within the prototype becomes part the Object that the prototype belongs to.

This is why my attempts to overwrite the method defined in the "class" function with a method defined in the prototype property was failing.

You cannot use the prototype property like inheritance, to overwrite the methods in the class that is is a part of.

You have to properly create a new derived class that inherits the first class in order to extend functionality in the base class.
Feb 20 '09 #11

gits
Expert Mod 5K+
P: 5,387
no problem ... glad i could have been of some help :)

kind regards,
gits
Feb 20 '09 #12

gits
Expert Mod 5K+
P: 5,387
@Frinavale
that's right except when you use inheritance ... as you see in my previous example ... the inheritance was made by overwriting the prototype of the child-obj with a new instance of the parent-class and then you could overwrite the inherited method with a new one ... in the child-obj's class

kind regards
Feb 20 '09 #13

gits
Expert Mod 5K+
P: 5,387
and just one more note for optimizing it a bit: when you create an instance without any parameters for the constructor then you might leave out the brackets ... this avoids the parsing of an empty args list for the parser and performs better ;)
Feb 20 '09 #14

Frinavale
Expert Mod 5K+
P: 9,731
@gits

Haha, don't try and confuse me now, I've finally got it!
:)

The only way to overwrite a method defined in a "class" function is to create a new "child-class" function. This child class is able to overwrite the methods in the parent-class.
Feb 20 '09 #15

Frinavale
Expert Mod 5K+
P: 9,731
Ok, now that I think I understand how Objects work in JavaScript, I'm off to look up how to implement a Singleton pattern using JavaScript.
Feb 20 '09 #16

gits
Expert Mod 5K+
P: 5,387
;) nope ... you could even do (for a specific instance):

Expand|Select|Wrap|Line Numbers
  1. function MY_OBJ() {}
  2.  
  3. MY_OBJ.prototype.my_func = function() {};
  4.  
  5. var o = new MY_OBJ;
  6.  
  7. o.my_func = function() { // new code here };
kind regards
Feb 20 '09 #17

gits
Expert Mod 5K+
P: 5,387
hmmm ... a singleton :) something like this:

Expand|Select|Wrap|Line Numbers
  1. function MY_OBJ() {
  2.     if (this.o != null) {
  3.         return MY_OBJ.prototype.o;
  4.     } else {
  5.         MY_OBJ.prototype.o = this;
  6.     }
  7. }
  8.  
  9. MY_OBJ.prototype.o = null;
  10.  
  11. MY_OBJ.prototype.my_func = function() {};
  12.  
  13. var o = new MY_OBJ;
  14.  
  15. o.foo = 'foo';
  16.  
  17. alert(o.foo);
  18.  
  19. var a = new MY_OBJ;
  20.  
  21. a.foo = 'bar';
  22.  
  23. alert(a.foo);
  24. alert(o.foo);
kind regards
Feb 20 '09 #18

Frinavale
Expert Mod 5K+
P: 9,731
:D

You know what's funny?
I decided that I don't actually want to use the Singleton in my solution.

;)

Thanks again Gits!
Feb 20 '09 #19

gits
Expert Mod 5K+
P: 5,387
*lol* ... but it's quite cool ;) ... nope ... serious ... when you have a look at it it makes use of the things we talked about before ... when we first create an instance we overwrite the prototype of the class and when the second instance should be created we just return a ref to the first created object ;)

kind regards
Feb 20 '09 #20

Frinavale
Expert Mod 5K+
P: 9,731
@gits
I was thinking the same thing.
It is pretty cool, and thanks to you it makes a lot of sense to me now.

I have a long way to go with JavaScript. As my ASP.NET applications become more complicated I'm finding that I have to use JavaScript more and more. It's a really good thing that you've helped me understand these basics now because I have a feeling everything's about to become a lot more complicated in my future.
Feb 20 '09 #21

gits
Expert Mod 5K+
P: 5,387
you know where to find help ;) ... JavaScript is quite cool!! :)

kind regards,
gits
Feb 20 '09 #22

Dormilich
Expert Mod 5K+
P: 8,639
@Frinavale
"Object Literal" (just to give that info)
Feb 21 '09 #23

Frinavale
Expert Mod 5K+
P: 9,731
@gits
I started debugging my original Ajax enabled .net server control (again...because it's not working in IE8... in fact it's crashing IE8 RC1). Upon researching a way around my problems I encountered numerous references to JSON with regards to these types of controls. Curious, I finally looked into JSON and now understand what you were referring to in your comment here.

@gits
I find it ironic that I had to experience this problem first hand myself even though you warned me about ""this"".
Mar 16 '09 #24

Post your reply

Sign in to post your reply or Sign up for a free account.