Understanding javascript prototype - javascript

I am learning about JS Prototype.
If I set a prototype of a constructor(A) from an instance of some other constructor(B), Is that instance (of B) would introduced shared properties in A?
Example 1
function A(){
var private = '';
this.getPrivate = function(){
return private
};
this.setPrivate = function(_private){
private = _private;
};
}
function B(){};
B.prototype = new A();
b1 = new B();
b2 = new B();
b1.setPrivate(new Date());
b2.getPrivate(); // Here `private` is behaving as singleton property. Why?
Example 2
function A(){
var private = '';
}
A.prototype.getPrivate = function(){
return this.private
};
A.prototype.setPrivate = function(_private){
this.private = _private;
};
function B(){};
B.prototype = new A();
b1 = new B();
b2 = new B();
b1.setPrivate(new Date());
b2.getPrivate(); // This time private is not singleton property.
I discovered this new aspect of prototype while playing with it.
In example 1, why private property is shared among different instances of B?
In example 2, why private property has independent presence in both instances? However original property is unchanged but the getter/setter are defined via prototype.
Can example 1 be considered an implementation of singleton properties?
Prototyping via instance and prototyping via prototype, What are the difference? e.g.
B.prototype = new A();
B.prototype = (new A()).constructor.prototype
What are the complete secrets of prototyping?

Because you are inheriting a specific instance locked down to specific closures. The data is owned by
the closures and not the object. There is a huge difference between variables and properties of object.
The var private is not used here at all. When you setPrivate() the property is created at that point.
No it's just accidental because of misunderstanding between closures and object model. You can do the same
in a much more deliberate and clearer way: by using a simple object literal.
The difference is that in first one you get a new object, where as in second one you have A.prototype === B.prototype so modifying
one will modify the other since they reference the same object.
Objects inherit from other objects
Here's a good resource https://developer.mozilla.org/en/JavaScript/Guide/Details_of_the_Object_Model

The secret of prototyping (which explains all of this) is that every instance of B shares the same prototype, i.e. prototype is not copied to new instances of B. When you fire a prototype function of any instance of B, you are actually running the same function all the time. That's why "private" variable is copied (actually it is not copied, you are just referencing the same variable all the time). "Nonprivate" variables behave the same, with the exception that the keyword this refers to the current "holder" of the function. That's why calling this in prototype gives us an illusion of prototype method being actually a method of an object. It is not.
Prototyping via instances is considered bad practice, because instances may have more or less properties depending on when they are called and when you are prototyping. Prototypes are mostly defined via literal object creation or extending prototypes of other objects.
And finally: in some sence prototyping may be interpreted as singleton.

In example 1, why private property is shared among different instances
of B?
Yes they do
In example 2, why private property has independent presence in both
instances? However original property is unchanged but the
getter/setter are defined via prototype.
Because each instance is independent of others. If that's not what you want use object literal notation to create your class.
Can example 1 be considered an implementation of singleton properties?
No because singleton always returns the same object instance. This relates to your second question where each instance is independent. One can create many instances of that class from your first example. To create singleton, there exists singleton or module pattern which uses self-invoking function with grouping operator eg wrapping function in ().
Prototyping via instance and prototyping via prototype, What are the
difference? e.g.
With constructor, you make sure that there is no confusion between your child class constructor and parent class. It is same concept when extending parent class, in child class you construct parent class in child class's constructor function.
What are the complete secrets of prototyping?
Going through good articles on various JS Ninja blogs. I love:
perfectionkills.com
javascriptweblog.wordpress.com
Here is good article:
Understanding JavaScript Prototypes.

In Example 1, you are using closure scope to refer to an private. Since A is only instantiated once, one instance of it is defined.
In Example 2, this.private does not refer to the instance of private in function A. In fact, since you use the word "this" it refers to the "this" of the object. Therefore, this.private either means b1.private or b2.private depending on the function. In Example 2, the private defined in Function A is lost to the closure scope and it's as if it was never defined.

Related

prototype inheritance and the prototype object, why isn't used to this extent?

I did a quick search but can't seem to find the answer to this question, just things referring to copying function prototypes when inheriting.
Why not add properties to the constructor functions prototype obj, instead of using the this keyword. I'm sure there is a reason not to, but I'm trying to understand the nuances of javascript better. for example in normal prototype inheritance you would "this".
function Dog(name,age,breed){
this.name=name;
this.age=age;
this.breed=breed;
}
Dog.prototype.bark=function(){console.log("bark bark bark");}
let spike=new Dog("Spike",6,"lab");
let rover=new Dog("Rover",8,"poodle");
//^with the constructor function, no instance has the bark function but
//but refers to the same function on the constructor prototype obj, so the
//same function isn't being duplicated. However new keyword changes the
//context of this to refer to the obj so these properties are duplicated
//on every instance.
//I'm curious as to the reason why new doesn't change this to refer to the
//prototype obj for example and then have the instance refers its
//constructor's prototype like with the bark function?
//for example why isn't this a common pattern and what are the reasons I
//should use it.
function Dog(name,age,breed){
Dog.prototype.name=name;
Dog.prototype.age=age;
Dog.prototype.breed=breed;
}
let spike=new Dog("Spike",6,"lab");
let rover=new Dog("rover",8,"poodle");
//I feel like the above code would be more DRY, I'm sure there is a reason
// this isn't common and I'm curious as to why
When you have properties on the prototype, you are overriding the properties with new values each time you instantiate the Class i.e in your example, from the two statements below :
let spike=new Dog("Spike",6,"lab");
let rover=new Dog("rover",8,"poodle");
Here, according to your expectation, spike.name should be Spike and rover.name should be rover, but if you execute this code and check, both of them are rover.
The properties of spike are overridden by the properties of rover when you created the new instance rover.
Each time, you create a new instance, the properties are overridden, the reason for this is
methods or properties attached to the prototype are created only once and are inherited to their sub classes every time a new instance is created.
The reason we create a Constructor function and new instances from it is because we have different properties for each instance like Spike and rover. In case of methods, methods are generic to a Constructor which can be reused for all the instances which need not be created every time a new instance is created, hence, we attach them to the prototype instead of defining it with this keyword in the Constructor.

JavaScript prototype vs. this in practice

I've read many questions with valid and understandable answers here in Stack Overflow and other sites over the web, and I think I understand everything I need for using JavaScript to make object-oriented apps, save one thing: What is the real, practical purpose of using a class' prototype over this?
I've read that any method, even one set as a this member, will be called from the constructor (class) function, and not re-created for each instance.
I've seen many examples of using prototype for setting methods, implying that it would save memory by using the original class-function's method on the instance, and not a brand new attribute.
So, along with remarking which of the two options above is true, I'd like to know: is a prototype method accessing the constructor's this ("public") variables or the instance's (which may have been set as different from the constructor's)?
Edit - is using this.prototype.method = function() inside the constructor's scope wrong? All examples I've seen set a prototype method after the function has been created.
I'll try to answer your question regarding the relationship between the prototype method and this by example.
From the moz docs:
If the method is on an object's prototype chain, this refers to the
object the method was called on, as if the method was on the object.
Example:
// Our constructor function
function Example() {
this.publicGreet = "Hello World";
};
// Here the function is set as a property of the constructors prototype
Example.prototype.greet = function() {
alert(this.publicGreet);
};
// This creates a new object and invokes the constructor function
// Sets publicGreet as a property of that object and assigns it the value "Hello World"
var exampleInstance = new Example();
// Looks up the prototype chain and invokes it as a method of exampleInstance
// Remember our definition of `this` for methods on the prototype chain?
// Hence, `this` refers to exampleInstance, therefore `this.publicGreet` is "Hello World"
exampleInstance.greet();
This test should explain the performance problem: http://jsperf.com/prototype-vs-instance-functions/6
But yes, prototype saves memory because one callback is defined and instances simply points to this callback. There's no need to declare bunch of copies of the same callback.
Access issue: "this" declared within function inside this.prototype refers to "this" of instance: http://jsfiddle.net/pHtjK/
var b = Function;
b.prototype.a = function(){alert(this.b);};
var xyz = new b();
b.b = 'what';
b.a();

understanding simple class emulator in JavaScript

Recently I started to learn a bit more advanced JavaScript (as far I only used jQuery for some simple tasks) and bought a book of Alex MaxCaw "JavaScript Web Applications". The first chapter treats about creating simple class emulator. I understand almost everything except for two lines of code marked with comments down below:
var Class = function(parent) {
var _class = function() {
this.init.apply(this, arguments);
};
if(parent) {
var subclass = function() {};
subclass.prototype = parent.prototype;
_class.prototype = new subclass();
};
_class.prototype.init = function() {};
_class.fn = _class.prototype;
//????
_class.fn.parent = _class;
//????
_class._super = _class.__proto__;
return _class;
};
Can anyone tell me what is purpose of these two lines? I'll be very thankfull.
Walking through the code:
Class is defined as a function that calls init with the arguments provided it. This means you can call it with standard constructor syntax using new eg. var instance = new Thingy() and get the init function called with the proper this value.
If you pass a parent class in, your class gets that class's prototype property added to the prototype chain of a new empty object which it uses as its prototype property. A more succinct way of doing this in modern browsers is _class.prototype = Object.create(parent.prototype);
The init function is defined. This should likely be overridden with more useful initialization code after a _class instance is created (or the code should be changed to allow the passing in of an init function when you create a Class... or allow the instance to walk the prototype chain to look for other init functions.
_class.fn is created to provide a reference to the _class constructor's prototype function.
_class.fn.parent is created to provide a reference back to the constructor. This may be useful if you are applying the prototype in some other context and want a reference back to the prototype's constructor.
_class._super is assigned the internal, non-standard __proto__ property of the constructor. Remember that constructors are functions and, in Javascript, functions are objects. This means they have their own internal prototypes. The earlier references to prototype are the prototype assigned to objects created with this constructor NOT the constructor's prototype itself. All functions inherit from Function.prototype, which is where they get bind, apply, etc. _super in this case is just a reference to Function.prototype.
As to when this type of _super is used, one could imagine doing the following:
function Maker(){ //this will be called as a constructor, ie. with new
var fun = function(){}; //Make a function
fun.__proto__ = this.__proto__; //yuck. Set the function's this value to the instance
return fun; //return the function
}
Maker.prototype={say:function(){console.log("Javascript is fun!.. And weird.")}};
var fun = new Maker();
fun.say() //"Javascript is fun!.. And weird."
console.log(fun.__proto__) // Object{say:function}
console.log(fun.bind) // undefined!!
Woah! What just happened?
In fact, you replaced your functions internal prototype with an Object. This allows you to build up interesting prototype chains and interact with both functions and objects in a similar way. Note, however, that the link with Function.prototype has been severed, which is why we don't have access to bind. However let's fix it with more prototype magic!
function FunctionConnector(obj){
for (var prop in obj){
if(obj.hasOwnProperty(prop){
this.prop=obj.prop
}
}
}
FunctionConnector.prototype=Function.prototype;
Maker.prototype=new FunctionConnector({say:function(){
console.log("Javascript is fun!.. And weird.")
}});
var fun = new Maker();
fun.say() //"Javascript is fun!.. And weird."
console.log(fun.__proto__) // Object{say:function}
console.log(fun.bind) // function bind(){ [native code] }
Now what is that FunctionConnector? It takes an object and, when called as a constructor, returns an object that both has all the properties of the passed object AND inherits from Function.prototype. As you can see, our access to bind has returned (Of course we also could have made do with our original implementation and just Function.prototype.bind.called our way to victory).
With this new pattern in hand it may be clearer what _super in your code does, namely it references the built in prototype of the _class constructor you are making (In our example the instance of FunctionConnector would be _super). This reference could be used to patch the prototype at runtime, call methods with apply or anything else you can due with a reference to an object.
This is, as you may have noticed a little hackish, especially since __proto__ is nonstandard. But it's also somewhat neat if you enjoy the patterns it allows. I'd recommend only doing something like this if you are very confident in your knowledge of Javascript inheritance, and perhaps not even then unless you are in charge of your entire code base.
From what i know, fn is just an alias to the prototype property
And about the _super, that one is for referencing to the "class" from which you are inheriting
Here's more about the use of _super and js inheritance: article

force prototype to have new parent-object in new instance of object

i'm looking for a way to force all of my objects have it's own instance of object in prototype. This object in prototype has it's own private variables. I don't want to share this objects. What should i do?
new function () {
"use strict";
function Controls() { };
Controls.prototype = new Application.Utils.Map(); //instance of this object is shared between all of new Controls objects. I want have new Map object for each new Controls Object.
Application.Stored.UI.Controls = new Controls();
Application.Stored.UI.Controls2 = new Controls();
}();
Map object looks like this:
function(){
//private variables with methods
return {
func: someFunc,
...
};
};
How to achieve this?
If privateness is more important to you than using prototype (prototype methods cannot access private instance variables) and you're not planning on cloning your instances ("private" instance variables can only be accessed by the instance not by the class as in Java). With inheritance then overriding parent's funcitons will be more complicated but there are ways to do it: (put all "class" code in the constructor function) How to call parent class' method from a subclass in JavaScript so that parent's local variables would be accessible?
I never use "private" instance variables but Bergi's suggestion to use module pattern is a good one to have "private" functions (not unique per instance) since a function can be the same for all instaces.
Added this as an answer instead of a comment because the question shows up as having 0 answers but I think Bergi did a good job answering the question in the comments.

Is there any benefit to using prototype instead of declaring properties on the object itself?

A prototype is used to declare properties and methods for a class of objects. One advantage of using prototype is that it conserves memory because all instances of a class point to the properties and methods of the prototype which conserves memory and effectively allows properties to be treated as static by all instances of a class.
Prototype is used for inheritance through prototype chaining.
My question is very simple. Why use prototype at all when you can just do:
function car() {
this.engine = "v8";
}
function mustang() {
// nm, no good way to inherit without using prototypes
}
Is that right? So the primary purpose of prototypes is threefold:
conserve memory
provide static properties
is the only way for a reference type to inherit from a super class
conserve memory
Yes it does, when you create hundreds of instances of Car and they all have their own functions (that have their own closure scopes) you'll consume more memory.
Can't find a reference for it but it has been suggested that Chrome optimises constructor functions that use prototype better than constructor functions with everything in the constructor body.
provide static properties
Static is more like Date.now(), every instance has members from the prototype but can be called on the instance.
is the only way for a reference type to inherit from a super class
You can inherit with Parent.apply(this,arguments); in Child but it makes extending Parent functions more complicated and doesn't make childInstance instanceof Parent true. What that code does is run Parent code with the to be created Child instance as the invoking object (this). Inheritance is usually done in 2 places.
In the Child body Parent.apply(this,arguments); to re use Parent initialisation code and make Parent instance members to be Child instance members (for example: this.name).
Setting Child.prototype to shallow copy of Parent.prototype Child.prototype=Object.create(Parent.prototype);Child.prototype.constructor=Child; This will ensure that shared Parent members are available on Child instances (like the function getName).
These points are explained in more detail here: https://stackoverflow.com/a/16063711/1641941
Concerning your three points:
Prototypes aren't necessarily more performant, especially for prototype chains that become long or contain many members. The smaller the prototype and shorter the chain, the more the browser's compiler can optimize it. Ultimately, this question needs to be asked for individual applications, their individual needs, and the browsers being targeted (which can vary widely in performance).
By definition, static members require objects. That is, static members belong to an object itself rather than to a specific instance. Objects are the only way to create static properties in JavaScript. Note that object literals, which are a "special" kind of Object, are essentially static.
One could implement his own type of object that would allow for something like inheritance (i.e., jQuery.extend), but as far as reference types go, prototypes are the only way to create inheritance.
Prototyping is a lot more than that.
You can also extend classes and already existing instances of objects with methods and properties during runtime.
This should explain it in a very understandable way: http://javascript.info/tutorial/inheritance
If you care about following conventions so that people (and you down the road) actually understand your code, you shouldn't put this.engine="v8" in the constructor. Prototype is meant to define properties for every single car, and the constructor is meant to define individual instances. So why would you put something that is true for every instance smack dab in the constructor? This belongs in the prototype. There's something to be said for putting things in their proper place even if doing both things end up doing accomplishing the same thing. Your code will be understandable by you and others.
Regarding your points:
There is definitely a performance boost, especially regarding functions - it's much better to declare functions on the prototype.
I think you meant to say "public" properties so that information is retrieved by writing some_instance.foo. "Static" properties/methods are different (see below).
Correct. Inheritance can only really happen from the prototype.
Let me explain some things to see if this helps. Creating new "classes" in javascript is a fairly straightforward process.
var MyClass = new Function();
At this point, the engine is aware of your new class and knows "what to do" (in terms of performance) when it creates new instances of your "class".
var my_instance = new MyClass();
If you want to modify the prototype, you can do so and know that every instance is going to get updated because they all share the same prototype.
MyClass.prototype.name = "default name";
console.log( my_instance.name ); //=> default name
Now the engine knows that there is a "name" property which expects a string value... it will allot those resources to all new AND existing instances of your class... which is very handy. Beware that modifying the prototype of an existing "class" like this is an expensive process and should not be performed frequently (but don't be afraid to do it either).
I can't really speak for the performance pros and cons of declaring ad-hoc properties/methods on an instance:
my_instance.foo = function() { /* this is not in the prototype chain */ };
My guess is that this is pretty simple for the engine and is no big deal unless you are doing this for tens of thousands of objects at the same time.
The main benefit of using the prototype IMO is that you can write code to extend a method's functionality and know that all instances of your "class" will get updated accordingly:
var old_foo = MyClass.prototype.foo;
MyClass.prototype.foo = function() {
/* new business logic here */
// now call the original method.
old_foo.apply(this, arguments);
};
Regarding "static" properties, you declare those on the "class" (constructor) itself:
// example static property
MyClass.num_instances = 0;
Now you can create init/destroy methods like this:
MyClass.prototype.init = function() {
this.constructor.num_instances++;
};
MyClass.prototype.destroy = function() {
this.constructor.num_instances--;
};
// and call the init method any time you create a new instance
my_instance.init();
console.log( MyClass.num_instances ); //=> 1
var instance_2 = new MyClass();
instance_2.init();
console.log( MyClass.num_instances ); //=> 2
instance_2.destroy();
console.log( MyClass.num_instances ); //=> 1
Hope that helps.
(1) I don't think conserving memory alone is a valid reason to utilize .prototype, unless you're getting really extreme with duplicating objects.
(2) The idea of static properties is not really a reason to use .prototype either (IMHO), because it doesn't behave like a traditional static property. You (as far as I know) always need an object instance before you can access the "static" property, which makes it not static at all.
function Car() {}
Car.prototype.Engine = "V8";
// I can't access Car.Engine... I'll always need an instance.
alert(new Car().Engine);
// or
var car1 = new Car();
alert(car1.Engine); //you always need an instance.
//unless you wanted to do
alert(Car.prototype.Engine); //this is more like a static property, but has an
//unintended consequence that every instance of Car also receives a .Engine
//behavior, so don't do this just to create a "static property."
It should be noted that this "static" idea not only applies to properties but all members, which includes methods (functions), from a traditional OO perspective.
It is better to think about prototypes (again, IMHO) as injected singleton objects with behaviors that get attached to instance objects. All instances of Car() can have their own instance members, but every instance of Car() will also "automatically" be injected with all Car.prototype's members/behaviors. It's not technically the same, but I find it convenient to think about prototypes in that way.
//define Car and Car.GoFast
function Car() {}
Car.prototype.GoFast = function () { alert('vroom!'); };
var car1 = new Car();
var car2 = new Car();
car1.GoFast();
car2.GoFast(); //both call to same GoFast implementation on Car.prototype
//change the GoFast implementation
Car.prototype.GoFast = function () { alert('vvvvvrrrrroooooooooommmmm!!!!!'); };
car1.GoFast();
car2.GoFast(); //both have been "updated" with the new implementation because
//both car1 and car2 are pointing to the same (singleton) Car.prototype object!
Car.prototype is behaving like a singleton object whose members/behaviors have been injected into instance objects of type Car.
(3) Prototypes shouldn't be confused for inheritance. You can get behavior that appears to be inheritance, but it is not. The members/behaviors on the prototype remain on the prototype object. They do not become members/behaviors of your derived class, like true inheritance. That is why I describe it more like the prototype being "injected" into your instance.
function Car() {}
Car.prototype.Engine = "V8";
var car1 = new Car();
var car2 = new Car();
alert(car1.Engine); //alerts "V8"
//There is no "Engine" variable defined within the instance scope of 'car1'.
//Javascript searches the scope of car1's Type.prototype object to find 'Engine'.
//Equivalent to: Object.getPrototypeOf(car1).Engine
//But if we create 'Engine' within the scope of car1
car1.Engine = "V6"; //Car.prototype was never accessed or updated
alert(car1.Engine); //we get "V6"
alert(car2.Engine); //we still get "V8"
alert(Object.getPrototypeOf(car1).Engine); //we still get "V8"!
So to answer the question directly: Is there any benefit to using prototype instead of declaring properties on the object itself?
Yes, when you want to share behavior implementation amongst instance objects of a given Type. As a coincidence, you will reduce your memory footprint, but that is not a reason alone to use prototypes. Neither is "creating static properties" (which they're not ), or for inheritance (which it is not).

Categories

Resources