7

I want to understand prototyping in javascript. For example:

1)

var MyObject = function() {
    this.a = "a";
    return this;
}

MyObject.prototype.fn = function() {console.log('1');}


var obj1 = new MyObject1();

2)

var MyObject = function() {
    this.a = "a";
    this.fn = function() {console.log('1');}
    return this;
}

var obj2 = new Object2();

I get obj1 and obj2 as the same. So, what I am doing in 2) is also prototype'ing? Or not? What am I missing about prototype?

Mert Mertce
  • 1,049
  • 7
  • 34
  • 1
    [Why Prototypal Inheritance Matters](http://aaditmshah.github.io/why-prototypal-inheritance-matters "Why Prototypal Inheritance Matters | Aadit M Shah") – Aadit M Shah Mar 31 '14 at 15:22
  • 1
    Just think of `MyObject.prototype` as an object that is shared by all objects created from the `MyObject` constructor. As such, even if you create 1,000 new object from `MyObject`, they will all share (inherit) all the properties of the `.prototype` object. – cookie monster Mar 31 '14 at 15:24
  • Thanks for all comments & answers. +1. I have to choose one as answer. – Mert Mertce Mar 31 '14 at 16:21
  • Prototype is shared and this.fn is created for every instance. For more info about prototype and inheritance see here: http://stackoverflow.com/a/16063711/1641941 – HMR Apr 01 '14 at 01:43

3 Answers3

4

2) is not prototyping

Here is a simple example, which explains the difference of the two methods:


1)

var MyObject1 = function() {
    this.a = "a";
    return this;
}

MyObject1.prototype.fn = function() {console.log('1');}

var obj1 = new MyObject1();

// change the prototype again
MyObject1.prototype.fn = function() {console.log('2');}

var obj2 = new MyObject1();

obj1.fn(); // logs '2'
obj2.fn(); // logs '2'

Here you change the prototype object after creating obj1, but nevertheless this change affects the object, because it has a reference to the current prototype object.

Because obj2 also has a reference to the prototype object, you also get '2' by calling the function fn.

Here all instances share the same prototype object.


2)

var MyObject2 = function() {
    this.a = "a";
    this.fn = function() {console.log('1');}
    return this;
}

var obj3 = new MyObject2();

// change the function
obj3.fn = function() {console.log('2');}

var obj4 = new MyObject2();

obj3.fn(); // logs '2'
obj4.fn(); // logs '1'

Here every object has it's own fn function. If one object changes the function, it will only affect the current object.

friedi
  • 4,350
  • 1
  • 13
  • 19
2

obj1 and obj2 are slightly different, i'll give you a quick explanation about prottypal inheritance in JavaScript.

A prototype is an object, just like any other object.

Every object that has a prototype will inherit from it all the properties and methods, overwriting them in case they are already defined in the object. Prototype references are live, this means, whenever you modify an object that's a prototype of another object, the changes reflect in that object.

You are using the pseudo-classical inheritance method, by wich you define a Constructor function that will return instances of a "class". All the instances of that class will have as their prototype object the object defined at: Constructor.prototype, and you can add methods or propertys to that prototype, and those will be added to every instance of the "class".

Why are obj1 and obj2 different?

obj1 doesn't hold a direct reference to the fn method, instead it holds a reference to the prototype, which has the method, and therefore obj1 has it aswell.

obj2 has a direct reference to the method, this means it's an own property of the object.

You can change the fn method of obj1 by changing the prototype's method, and any other instance of MyObject (like obj1) will be changed aswell.

But you can't do that in obj2, if you modify obj2's method you'll just replace the method of that instance.

I hope you got something, just ask if you have any doubts.

About the writing "class": JavaScript does't have classes, it emulates Class inheritance with prototypes, you can use crude prototypal inheritance using Object.create, and you'll see it's way easier.

user3417400
  • 341
  • 2
  • 4
1

Say we have

var A = new Object1(),
    B = new Object1(),
    X = new Object2(),
    Y = new Object2(),
    fn2 = function () {
        console.log(2);
    };

Consider (reset for each)

    • A.fn === B.fn; // true
    • X.fn === Y.fn; // false
    • Object1.prototype.fn = fn2 then A.fn(); // 2
    • Object2.prototype.fn = fn2 but X.fn(); // 1
    • A.fn = fn2 now A.fn(); // 2 but B.fn(); // 1
    • X.fn = fn2 now X.fn(); // 2 but Y.fn(); // 1
    • "fn" in A; // true but A.hasOwnProperty("fn"); // false
    • "fn" in X; // true and X.hasOwnProperty("fn"); // true

What can we learn from this?
Prototyping shares across the instances but doesn't set properties directly on them, whereas setting a property in the constructor creates new and separate properties each time.

Paul S.
  • 64,864
  • 9
  • 122
  • 138