2

I was reading the developer.mozilla.org guide to OOP JS and came across this snippet:

function Person(gender) {
  this.gender = gender;
}

Person.prototype.gender = '';

Person.prototype.sayHello = function () {
  alert ('hello');
};

var person1 = new Person('Male');
var person2 = new Person('Female');

// call the Person sayHello method.
person1.sayHello(); // hello

I don't understand, if (gender) is already defined as this.gender; why do we need to put the Person.prototype.gender = ''; line? I understand it for functions outside of the constructor, but it seems like that line is repeating the this.gender; line. I understand it is creating gender as a property of the Person() object, but doesn't that just repeat the this.gender?

I would appreciate any explanation, I'm new to OOP JS. Thanks!

2
  • In this instance, you just don't need it. Usually such is only done if a property is only conditionally created, and inheriting a default value from the prototype otherwise. Commented Apr 27, 2014 at 20:46
  • While it is really technical and not directly related to your question this could be of interest: Should I put default values of attributes on the prototype to save space?. Commented Apr 27, 2014 at 21:31

3 Answers 3

5

By adding Person.prototype.gender = ''; the Person has a "default" gender persay. It is more like defining a gender for the Person if no gender is specified at instantiation. Keep in mind, setting this.gender = gender when gender is undefined still counts as specifying a value.

When it becomes obvious is if you try to delete the gender property from your persons. If Person.prototype.gender = ''; is omitted, then the following situations can occur:

var person1 = new Person('Male');

// check gender
person1.gender === 'Male'; // true

// remove gender property from person1
delete person1.gender;

person1.gender === undefined; // true

Because person1 does not have gender anymore, it cannot reference it in this Person instance, so it will look up its prototype chain at the Person constructor. And it won't find it there because in the constructor this.gender = gender; is a instance property. The lookup process continues up the prototype chain until it finds the property.

Now consider if we have the following:

function Person(gender) {
  this.gender = gender;
}

Person.prototype.gender = 'Asexual';

var person1 = new Person('Male');
var person2 = new Person('Female');
var person3 = new Person();

// check genders, looking at instance property
person1.gender === 'Male'; //true
person2.gender === 'Female'; //true
person3.gender === undefined; //true

// remove their genders
delete person1.gender;
delete person2.gender;
delete person3.gender;

// check genders again, now it's looking up the prototype chain 
person1.gender === 'Asexual'; //true
person2.gender === 'Asexual'; //true
person3.gender === 'Asexual'; //true
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot, that's exactly what I wanted. It makes sense that the Object.Prototype.Property would be a fall back.
1

The short answer is that the line is only there for a default value, you are essentially doing something like this:

function Person(gender) {
  this.gender = gender || '';
}

Person.prototype.sayHello = function () {
  alert ('hello');
};

var person1 = new Person('Male');
var person2 = new Person('Female');

// call the Person sayHello method.
person1.sayHello(); // hello

If, you create a Person and you don't pass in a gender, this.gender is set to undefined;

So when you look the property up, it will look up property on the object itself. That will turn out to be undefined, so it will then try to look it up on the prototype and find the empty string which is not undefined.

Therefore, it's only a default value in this case, and it's totally fine to not use this pattern ever and only use prototype for methods, and not values.

2 Comments

Assuming you call the OP's code with person2 = new Person() then person2.gender is undefined, as it is set to undefined (it is a property set to undefined) only if you call delete person2.gender then the property gender is unset, and then the value of the prototype will be looked up and return '' in that case. So having this.gender = gender will not use the Person.prototype.gender = ''; as default if no parameter is passed.
Then what is the point of setting Person.prototype.gender if this.gender won't default to the prototype value if no parameters are passed? I have ran the code both with and without the Person.prototype.gender line and it works either way so I figured that it makes sense to default to the prototype value if no parameters are passed in but since that's not the case what's the point of it?
0

Perhaps a slightly different syntax may help to define the default you are asking about

var Person = (function () {
    function Person(gender) {
        this.gender = gender || '';
    }
    Person.prototype.greet = function () {
        return "Hello, " + this.gender;
    };
    return Person;
}());

// Create instance
var greeter = new Person();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.