JavaScript prototype vs. this in practice - javascript

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();

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.

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

Understanding javascript prototype

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.

JavaScript OOP: method definition with or without "prototype"

Is this code,
function Person() {
function myMethod() {
alert ('hello');
}
this.method = myMethod;
}
equivalent to:
function Person() { }
Person.prototype.method2 = function() {
alert ('hello');
};
If yes, which method definition should I use and why?
They are functionally equivalent in your simple example, but behind the scenes work very differently. The prototype property on a function is really the "prototype template". It says "whenever an object is made and I am used as the object's constructor, give them this object as their prototype".
So all Persons created in your second example share the same copy of the method2 method.
In the first example, each time the interpreter encounters the function keyword, then it creates a new function object. So in the first example, each instance of Person has their own copy of the myMethod method. The vast majority of the time this doesn't matter. But this first approach uses more memory, and sometimes that does matter.
They are not functionally equivalent in more interesting cases. In the first example, myMethod can access local variables defined in Person, but the second example cannot, as one difference.
In the first scenario, when you create a new person, var person1 = new Person();, it will have its own copy of myMethod. If you create 100 Person objects, they will each have their own copy of this method.
Using a prototype, every new Person object will share the method definition. This is much more memory efficient since there will only be one copy of the method.
If you are planning on having several Person objects, the second way is better.. but if there are only a few Person objects, it won't matter that much.
It is not entirely equivalent.
In both cases, you define a function (constructor) Person() in the global namespace.
In the first case, you define a new function myMethod() in a closure inside the Person() function. Normally, the myMethod() function would not be available after the function/constructor Person() finishes. However, in this case you assign it to this.method. Thus, when you run the constructor
var myPerson = new Person();
A new object is created, then the Person() function is called with this set to the new object. Therefore, your new object receives a method field with myMethod function bound to it.
In the second case, method2 is defined inside the Person.prototype. In this case, when you call
var myPerson = new Person();
there will be no field defined directly inside your new object (as you do nothing with this in the function Person). However, every object contains a reference to its prototype. If the object is created by calling Person(), this reference is set to Person.prototype. Thus, your object will ultimately contain method2, though not directly in itself, but in the prototype. So when you call
myPerson.method2();
the interpreter looks for method2 inside the myPerson object and finds nothing, then it looks into the prototype of myPerson, which is Person.prototype and finds method2, so it calls it.
Long story short: in the first your constructor creates the method, so every time you call the constructor, a new method is created and inserted to the new object. In the second case, the method is stored in the prototype, so every object you create will have the reference to the same instance of your method.
No, they are not equivalent. Although, they are similar. The first method will create a new function myMethod for each new Person() created.
The second method will have one function method2 that is "shared" by all Person's.
They have similar functionality but you should use the second approach (prototype) because when you will create an object using new Person() every object will share the same method2 but using the first approach each new object will have it's own myMethod() that will consume moe memory.
A few days ago I asked a similar question and got this answer.

How does an object reference itself in Javascript?

I was experimenting with inheritance in javascript, and wrote those two functions:
Object.prototype.inherits=function(obj){this.prototype=new obj;}
Object.prototype.pass=function(obj){obj.prototype=new this;}
This code works very well:
Dog.inherits(Animal);
But the following fails:
Animal.pass(Dog);
As I understand it, my pass functions doesn't work, because "this" isn't a reference to the object instance itself? If that's the case, how can I reference the object from within itself?
Thanks in advance!
Well, actually the two are doing exactly the same:
Dog.prototype = new Animal;
The this value inside the methods will refer to the base object where the reference was invoked, in the case of:
Dog.inherits(Animal);
The this value will refer to the Dog constructor function, and the obj argument will be the Animal function.
When you call:
Animal.pass(Dog);
The this value will refer to the Animal function, doing at the end exactly the same thing as the inherits method, but the other way around.
I would recommend you to not extend the Object.prototype object, because it can cause you a lot of problems, for example those two properties will be enumerated in any for-in loop, e.g.:
for (var prop in {}) { // <-- an empty object!
alert(prop); // will alert 'inherits' and 'pass'
}
All objects inherit from Object.prototype, and it seems that you intend to use those methods only on Function objects, it would be safer to extend the Function.prototype object, or implement the methods as functions that take two parameters.
Works for me, with test code like:
function Animal() {}
Animal.prototype.isanimal= 1;
function Dog() {}
Animal.pass(Dog);
Dog.prototype.isdog= 2;
alert(new Dog().isanimal); // 1
alert(new Dog().isdog); // 2
However, bear in mind that new this or new obj will call the function this/obj, creating a new full instance. If you have constructor code in that function that expects to receive some arguments, or sets up instance state, you can end up with problems. To create a new this without calling this as a function you can use a different constructor that does nothing:
function nonconstructor() {}
nonconstructor.prototype= this.prototype;
obj.prototype= new nonconstructor();
Also, you should avoid prototyping onto Object. This will cause trouble for code using Object as a general-purpose lookup map. As you only seem to be working with constructor-functions, prototyping onto Function should meet your needs and is much safer.

Categories

Resources