0

I'm reading MDN Javascript for beginners and it's saying you can create a constructor function then make object instances based on that constructor. Now you have access to the properties and methods defined in the constructor. However, then they go on to say only properties and methods defined on the constructor prototype property are available to object instances, at least as I understand. Can someone clear this up because the instance seems to have access to these with no prototype property defined in the example. Thank you

function Person(first, last, age, gender, interests) {
    this.name = {
        first,
        last
    };
    this.age = age;
    this.gender = gender;
    this.interests = interests;
    this.bio = function() {
        alert(this.name.first + ' ' + this.name.last + 
              ' is ' + this.age + ' years old.'+
              ' He likes ' + this.interests[0] +
              ' and ' + this.interests[1] + '.');
        };
        this.greeting = function() {
            alert('Hi! I\'m ' + this.name.first + '.');
        };
    }

    var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);

    person1['age']
    person1.interests[1]
    person1.bio()
    // etc.

4 Answers 4

3

Anything that's attached to the prototype property of a constructor is shared between all instances created using the constructor. The values are the same in all such objects.

The constructor can also attach individual properties to the object being created. These are specific to the new instance, and are not shared.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the reply. I'm just still not getting it. Isn't the bio() function in the example above going to be available to all instances even though it's not in a prototype property?
Might want to clarify that this in the constructor refers to the object being created, not the class object
@JohnAuer there will be a copy of the bio function attached to each instance of the class. Would be better to put it in the prototype. (Each time the Person constructor is executed, it assigns a newly created anonymous function to the bio property)
2

So, Javascript objects work A LOT differently than in other programming languages. Well, most mainstream ones anyway.

Here's the deal - a Javascript object is really just a dictionary (aka map). For example:

var x = {}; // creates a new blank object
x.something = 42; // creates a property on the object and assigns value to it
x['something'] = 15; // Alternate syntax. Assigns to the same property we just created.
x['yo, this is valid too!'] = true; // Yes, this is valid too.

See what I mean? It's just a dictionary, you can set whatever you want. And unset too - that's what the delete operator does.

So what about those constructors and prototypes? Well, any function can be used as a constructor. When you go like

var x = new foo();

What really happens is that Javascript creates a new blank object and then calls the foo() while putting the newly created object in this. And lo and behold, it kinda looks like a constructor.

There's actually a little quirk that needs to be mentioned. If the constructor function returns a value, then Javascript uses that instead of the newly created object. So if you do this:

function foo() {
    this.meaning = 42;
}

var a = new foo();

Then a will contain the blank object that Javascript created for you. But if you do this:

function foo() {
    this.meaning = 42;
    return {nope: 3};
}

var a = new foo();

Then a will contain the {nope : 3} object instead. OK, but that's rarely used.

Anyway, where were we? Ah, yes, prototypes. Oh, wait, first another thing needs to be explained. In Javascript EVERYTHING is an object. So, like, these things are completely valid:

var a = 42;
var b = "hello, world";

a.foo = "yay";
b.bar = 10;

And, just to really blow your mind there, functions are objects too. First class citizens, so to speak. This is all valid:

function foo() {
}

foo.bar = "baz";

var x = foo;

Yup, you can treat functions just like any other object. You can put them in variables, pass them to other functions in parameters, assign and delete arbitrary properties to them, you name it. This is a feature rarely found in other languages, so it's probably the hardest thing to wrap your mind around. I know my mind was blown when I first understood this.

Now we can talk about prototypes. You see, every function in Javascript also has a special magical property called prototype. By default, it's set to a blank object. But you can set it to another object. Or you can add/delete properties to the existing blank object. It's just another object, nothing fancy about it.

Furthermore, every object in Javascript has a special magical property called __proto__. Remember that when you call new foo() a new object is created and passed to foo() as this? Well, that new object has its __proto__ set to whatever foo.prototype was at the time.

Now suppose you do this:

function foo() {
    this.a = 42;
}

foo.prototype.b = 15;

var x = new foo();

If you then type x.a then x has such a property and all is well. But if you type x.b then x doesn't have such a property, and that's where the magic happens. Javascript automatically checks if there is a x.__proto__.b and if there is, returns that! And if there isn't, it checks x.__proto__.__proto__.b, etc, until it hits an object with __proto__ == null and then it gives up and just returns undefined since there is no such property.

On the other hand, when you now do this:

x.b = "foobarbaz";

Then the b property is created directly on the x object. The prototype remains unchanged.

So this is how you create "inheritance" in Javascript. With the prototypes. It's different than in your typical class-based language, but no less powerful.

There are some other nuances and tricks that could be mentioned, as well copious amounts of examples to help you grok all this, but... I've run out of juice for today. :) This should answer the question as well as hopefully make more sense of whatever other tutorial you are reading.

2 Comments

Wow....thanks for such an elaborate answer. That helped clear things up a lot! :)
Good answer, complexity/succinctness ratio
0

Jules is right.

To go in further detail: You have this constructor.

function Person(first, last, age, gender, interests) {
    this.name = {
        first,
        last
    };
    this.age = age;
    this.gender = gender;
    this.interests = interests;
    this.bio = function() {
        alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
    };
    this.greeting = function() {
        alert('Hi! I\'m ' + this.name.first + '.');
    };
}

Now you can create to instances of it...

var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
var person2 = new Person('Anne', 'Smith', 32, 'male', ['music', 'skiing']);

If you access the prototype and change it every other instance will also have this change.

person1.__proto__.attrX = "Hello World"
alert(person2.attX)

All this Javascript prototype inheritance may be very confusing at first but you actually almost never required. I actually wouldn't even recommend it because it is tempting to mess around with. For instance you could have the idea to change the prototypes of basic datatypes in JS. For instance like so:

Person.__proto__.arguments = "";

This is very very bad. Especially if you actually wanted to do this:

Person.prototype.arguments = "";

If you are not aware of the difference between prototype and __proto__. They are basically the same on different perspectives.

  • __proto__ refers to the constructor of an instance
  • prototype does the same if you use it on constructors

But because a constructor itself is an instance of function you will always refer to the constructor of function if you call __proto__ on a constructor directly. So changing something on the function constructor would change all the function withing JS and this could interfere if you change something so integral to functions such as arguments. You see it becomes very nasty if you dive deeper into it... But you can just avoid those things.

1 Comment

"Object.is(), Object.keys(), and other members not defined inside the prototype bucket are not inherited by object instances. They are methods/properties available just on the Object() constructor itself."-MDN....But when it's on the constructor, don't the instances inherit it just like bio() in the first example?
0

javascript object inheritance relationship

I just learned the javascript object inheritance relationship yesterday and made a graph according to this good description. Hope it is useful to you.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.