javascript tutorial - [Solved-5 Solutions] Use of ‘prototype’ vs.’this’ in javascript? - javascript - java script - javascript array



Problem:

What's the difference between

var A = function () {
    this.x = function () {
        //do something
    };
};
click below button to copy the code. By JavaScript tutorial team

and

var A = function () { };
A.prototype.x = function () {
    //do something
};

click below button to copy the code. By JavaScript tutorial team

Solution 1:

As others have said the first version, using "this" results in every instance of the class A having its own independent copy of function method "x". Whereas using "prototype" will mean that each instance of class A will use the same copy of method "x". Here is some code to show this subtle difference:

// x is a method assigned to the object using "this"
var A = function () {
    this.x = function () { alert('A'); };
};
A.prototype.updateX = function( value ) {
    this.x = function() { alert( value ); }
};

var a1 = new A();
var a2 = new A();
a1.x();  // Displays 'A'
a2.x();  // Also displays 'A'
a1.updateX('Z');
a1.x();  // Displays 'Z'
a2.x();  // Still displays 'A'

// Here x is a method assigned to the object using "prototype"
var B = function () { };
B.prototype.x = function () { alert('B'); };

B.prototype.updateX = function( value ) {
    B.prototype.x = function() { alert( value ); }
}

var b1 = new B();
var b2 = new B();
b1.x();  // Displays 'B'
b2.x();  // Also displays 'B'
b1.updateX('Y');
b1.x();  // Displays 'Y'
b2.x();  // Also displays 'Y' because by using prototype we have changed it for all instances
click below button to copy the code. By JavaScript tutorial team

As others have mentioned, there are various reasons to choose one method or the other. My sample is just meant to clearly demonstrate the difference.

Solution 2:

In most cases they are essentially the same, but the second version saves memory because there is only one instance of the function instead of a separate function for each object. A reason to use the first form is to access "private members". For example:

var A = function () {
    var private_var = ...;

    this.x = function () {
        return private_var;
    };

    this.setX = function (new_x) {
        private_var = new_x;
    };
};
click below button to copy the code. By JavaScript tutorial team

Because of javascript's scoping rules, private_var is available to the function assigned to this.x, but not outside the object.

Solution 3:

The first example changes the interface for that object only. The second example changes the interface for all object of that class.

Solution 4:

The ultimate problem with using this instead of prototype is that when overriding a method, the constructor of the base class will still refer to the overridden method. Consider this:

BaseClass = function() {
    var text = null;

    this.setText = function(value) {
        text = value + " BaseClass!";
    };

    this.getText = function() {
        return text;
    };

    this.setText("Hello"); // This always calls BaseClass.setText()
};

SubClass = function() {
    // setText is not overridden yet,
    // so the constructor calls the superclass' method
    BaseClass.call(this);

    // Keeping a reference to the superclass' method
    var super_setText = this.setText;
    // Overriding
    this.setText = function(value) {
        super_setText.call(this, "SubClass says: " + value);
    };
};
SubClass.prototype = new BaseClass();

var subClass = new SubClass();
console.log(subClass.getText()); // Hello BaseClass!

subClass.setText("Hello"); // setText is already overridden
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
click below button to copy the code. By JavaScript tutorial team

versus:

BaseClass = function() {
    this.setText("Hello"); // This calls the overridden method
};

BaseClass.prototype.setText = function(value) {
    this.text = value + " BaseClass!";
};

BaseClass.prototype.getText = function() {
    return this.text;
};

SubClass = function() {
    // setText is already overridden, so this works as expected
    BaseClass.call(this);
};
SubClass.prototype = new BaseClass();

SubClass.prototype.setText = function(value) {
    BaseClass.prototype.setText.call(this, "SubClass says: " + value);
};

var subClass = new SubClass();
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
click below button to copy the code. By JavaScript tutorial team

If we think this is not a problem, then it depends on whether we can live without private variables, and whether we are experienced enough to know a leak when we see one. Also, having to put the constructor logic after the method definitions is inconvenient.

var A = function (param1) {
    var privateVar = null; // Private variable

    // Calling this.setPrivateVar(param1) here would be an error

    this.setPrivateVar = function (value) {
        privateVar = value;
        console.log("setPrivateVar value set to: " + value);

        // param1 is still here, possible memory leak
        console.log("setPrivateVar has param1: " + param1);
    };

    // The constructor logic starts here possibly after
    // many lines of code that define methods

    this.setPrivateVar(param1); // This is valid
};

var a = new A(0);
// setPrivateVar value set to: 0
// setPrivateVar has param1: 0

a.setPrivateVar(1);
//setPrivateVar value set to: 1
//setPrivateVar has param1: 0
click below button to copy the code. By JavaScript tutorial team

versus:

var A = function (param1) {
    this.setPublicVar(param1); // This is valid
};
A.prototype.setPublicVar = function (value) {
    this.publicVar = value; // No private variable
};

var a = new A(0);
a.setPublicVar(1);
console.log(a.publicVar); // 1
click below button to copy the code. By JavaScript tutorial team

Solution 5:

What's the difference? => A lot. WE think, the this version is used to enable encapsulation, i.e. data hiding. It helps to manipulate private variables. Let us look at the following example:

var AdultPerson = function() {

  var age;

  this.setAge = function(val) {
    // some housekeeping
    age = val >= 18 && val;
  };

  this.getAge = function() {
    return age;
  };

  this.isValid = function() {
    return !!age;
  };
};
click below button to copy the code. By JavaScript tutorial team

Now, the prototype structure can be applied as following: Different adults have different ages, but all of the adults get the same rights. So, we add it using prototype, rather than this.

AdultPerson.prototype.getRights = function() {
  // Should be valid
  return this.isValid() && ['Booze', 'Drive'];
};
click below button to copy the code. By JavaScript tutorial team
var p1 = new AdultPerson;
p1.setAge(12); // ( age = false )
console.log(p1.getRights()); // false ( Kid alert! )
p1.setAge(19); // ( age = 19 )
console.log(p1.getRights()); // ['Booze', 'Drive'] ( Welcome AdultPerson )

var p2 = new AdultPerson;
p2.setAge(45);    
console.log(p2.getRights()); // The same getRights() method, *** not a new copy of it ***

click below button to copy the code. By JavaScript tutorial team

Related Searches to javascript tutorial - Use of ‘prototype’ vs ’this’ in javascript