difference between using this and prototype to define methods of a class in JavaScript? [duplicate]
When creating a class in JavaScript, how is declaring methods inside the object using this different then declaring it by accessing the prototype ? it seems to me to serve the same purpose.
window.onload = function() < tc = new TestClass(); tc.init(); //logs initting tc.reset(); //logs resetting tc.doSomething(); //logs doing something >; var TestClass = function() < this.init = function()< console.log("initting"); >this.reset = function() < console.log("resetting"); >this.destroy = function() < console.log("destroying"); >> TestClass.prototype.doSomething = function()
3 Answers 3
In most situations you will have the same functional result. But internally it’s quite different in that when you attach the functions to this , then every instance of the type gets its own copy of the function. By attaching the functions to prototype , all instances share the same function instances. Using prototype reduces memory usage.
@nuway: Try not to think of it too much in classical terms; it’ll drive you crazy when the illusion breaks. JS doesn’t have classes, and thus doesn’t have static . In JS, you have prototypes (which are just regular objects), and other objects inherit directly from the prototype rather than its class. That is, the prototype is an instance. Stuff on the prototype is inherited by everything that inherits from the prototype. but it’s not «static», as any function in the prototype can still work on this and do the right thing.
What’s more, the «static» stuff can be overridden at will without breaking sibling objects. If there’s an x on your prototype with a value of ‘1’, and you say this.x = 0; , you get your own x — that looks just like the prototype’s version (except for the different value, of course, and you.hasOwnProperty(‘x’) returning true ) to any function that messes with you, even functions in the prototype.
Before you read: English is not my mother language 😉
In practice both this and prototype is almost the same, but this and prototype has distinct meaning in javascript.
1) Javascript is based on prototype inheritance. What this mean is that one object can inherit the prototype model from another object. Using prototype you can emulate inheritance on javacript (with limitations), for example:
// create a 'class' Vehicle var Vehicle = function() <>; Vehicle.prototype.wheels = 0; Vehicle.prototype.maxSpeed = 0; Vehicle.prototype.displayInfo = function() < alert("hello, I have " + this.wheels + " wheels and max speed of " + this.maxSpeed); >; var vehicleInstance = new Vehicle(); vehicleInstance.displayInfo(); // displays: Hello, I have 0 wheels and max speed of 0 // create a 'class' Car using the prototype from Vehicle // and change some properties. var Car = function(maxSpeed) < if(maxSpeed) this.maxSpeed = maxSpeed; >; // inherit the prototype from vehicle Car.prototype = new Vehicle(); // change some properties Car.prototype.maxSpeed = 200; Car.prototype.wheels = 4; var car = new Car(); car.displayInfo(); // displays: Hello, I have 4 wheels and max speed of 200
2) Properties in this has precedence over properties in prototype, for example:
var car = new Car(); // car prototype: maxSpeed = 200; car.displayInfo() // displays: Hello, I have 4 wheels and max speed of 200 //set maxSpeed to 300 on 'this' var car = new Car(300); // see Car definition above // call displayInfo() in car instance. The Car 'class' doesn't have displayInfo() // itself, but its prototype has. The javascript VM will look // for displayInfo() in the car instance, if it not found in the // instance it will look in car.prototype and on car.prototype.prototype etc. // until it founds a property called displayInfo() // or reaches the end of the chain (Object.prototype). car.displayInfo() // displays: Hello, I have 4 wheels and max speed of 300
This also applies for the prototype of the prototype, for example.
var Class1 = function() < >; Class1.prototype.someValue = 1; var Class2 = function() < >; Class2.prototype = new Class1(); Class2.prototype.someValue = 2; // this overrides the Class1.prototype.someValue prototype var class2 = new Class2(); class2.someValue = 3; // this overrides the Class2.prototype.someValue;
3) Properties defined on prototype are not instantiated for every new instance of the same object, for example:
// create a new class and inherit the prototype model from Vehicle. var Motorcycle = function() < >; Motorcycle.prototype = new Vehicle(); // motorcycles has 2 wheels Motorcycle.prototype.wheels = 2; var motorcycle = new Motorcycle(); motorcycle.dysplayInfo(); // displays: Hello, I have 2 wheels and max speed of 200 //now, if I change the method dysplayInfo from Vehicle, it will change for every //object that inherits Vehicle prototype: Vehicle.prototype.displayInfo = function() < Alert("Wheels: " + this.wheels + ", Max speed: " + this.maxSpeed); >//observe that I didn't create another Motorcycle instance , //I'm using the same instance that I've created before change //the Vehicle.dysplayInfo() method motorcycle.displayInfo() // displays: Wheels: 2, Max speed: 200
As you can see, the same method used in Vehicle is used by any object that inherits his prototype. This make your code much more efficient, since you’re using the same function for more than one object. You can have thousands of objects inheriting from a fat prototype and still get a low memory footprint.
In short: By using prototype you are able to create powerful ‘classes like’ objects, with a well defined inheritance tree (we say prototype chain) which will run more efficiently and will use less memory.
What I have said here does not exhaust the subject of prototype inheritance/chain. Here are other resources you can read. I recommend since understand prototypes in javascript is essencial to write good and maintainable code.