Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objects types in Javascript

This is a fairly general question coming from a newbie in the learning phase and is on something I need clarifying.

I'm currently learning about objects and at this point I'm learning about inheritance. At this point in the lesson I've learned a few different ways to create objects but objects using the this keyword seems to have the most function:

function Person(){
    this.eyes = 2;
    this.ears = 2;
    this.arms = 2;
    this.hands = 2;
    this.feet = 2;
    this.legs = 2;
    this.species = "Homo sapien";
    }

I understand what I might use this for but then there's an object created this way:

var person = new Object();
person.eyes = 2;
person.ears = 2;
person.arms = 2;
person.hands = 2;
person.feet = 2;
person.legs = 2;
person.species = "Homo sapien";

Because I seem to be able to do things with the former that I can't do with the latter, I'm wondering if there's any reason why I wouldn't just use the former method all the time. Can anyone help me out with this? I don't need a long detailed answer (although one would be appreciated). It's just a question I want to get out of my head so that I don't dwell on it.

like image 686
AGx-07_162 Avatar asked Aug 18 '15 15:08

AGx-07_162


People also ask

What are the objects in JavaScript?

In JavaScript, an object is a standalone entity, with properties and type. Compare it with a cup, for example. A cup is an object, with properties. A cup has a color, a design, weight, a material it is made of, etc.

What are three types of objects supported by JavaScript?

Data Types in JavaScriptObject, Array, and Function (which are all types of objects) are composite data types. Whereas Undefined and Null are special data types.

How many types of objects can be created in JavaScript?

You can create an object in three different ways: Using object literal. By creating instance of Object directly. By using constructor function.

What are 3 types of data in JavaScript?

JavaScript allows you to work with three primitive data types: numbers, strings of text (known as “strings”), and boolean truth values (known as “booleans”). JavaScript also defines two trivial data types, null and undefined, each of which defines only a single value.


1 Answers

Preface: If you're not sure what I mean by the word "prototype" below, skip down to below the divider for an explanation, then come back up here to the top of the answer. :-)


Assuming in your first example that you then call Person via new:

var person = new Person();

...then the only difference between that person and the one you'd get using your second example is related to inheritance: The one created via new Person gets assigned the object on Person.prototype as its underlying prototype.

I'm wondering if there's any reason why I wouldn't just use the former method all the time

If you don't need to use the prototype, then using a constructor function could be unnecessarily complicated. Note that your second form could more concisely be written:

var person = {
    eyes: 2,
    ears: 2,
    arms: 2,
    hands: 2,
    feet: 2,
    legs: 2,
    species: "Homo sapien"
};

That's called an object initializer: It creates a new object with the properties you see listed. There's never any need to use x = new Object(); if you want a new, blank object, just use x = {};.

When an object is a one-off, creating it directly is often the simplest way to create it.

The key advantage constructor functions have is that they're factories for objects that are fundamentally similar: Have the same set of initial properties, have the same underlying prototype, etc. And the function can accept arguments and use them to outfit the object it's creating in an appropriate way, perhaps do some validation on the construction arguments, etc. That is: They centralize initialization logic.

Constructor functions are not the only way to have function factories. You can also do:

function buildPerson() {
    return {
        eyes: 2,
        ears: 2,
        arms: 2,
        hands: 2,
        feet: 2,
        legs: 2,
        species: "Homo sapien"
    };
}
var person = buildPerson();

And if you want that person to have a prototype (ES5 browsers and higher):

var personPrototype = {
    // ...properties for the person prototype...
};
function buildPerson() {
    var obj = Object.create(personPrototype);
    obj.eyes = 2;
    obj.ears = 2;
    obj.arms = 2;
    obj.hands = 2;
    obj.feet = 2;
    obj.legs = 2;
    obj.species = "Homo sapien";
    return obj;
}
var person = buildPerson();

(There's another, more verbose way to define those properties as well.)

JavaScript is amazingly flexible. :-)


"Prototype"

JavaScript uses prototypical inheritance, which is a fancy way of saying that a object A can be "backed" by object B so that if you ask A for a property it doesn't have, the JavaScript engine will look to see if that property exists on B. A quick practical example:

var proto = {
    name: "proto's name"
};
var obj = Object.create(proto); // Creates an object backed by the given prototype

Don't worry about Object.create, for now all you need to know is that it creates a new object and assigns its underlying prototype based on the object you pass into it. So obj is backed by proto.

obj doesn't have a name property, but if we do:

console.log(obj.name);

...we see "proto's name". That's because when the JavaScript engine tried to get name's value from obj, it found that obj didn't have a name property, so it looked to obj's prototype, proto. Having found it there, it used the value from proto.

That only happens when getting the value (except in some advanced cases we can ignore for now). When setting a property's value, it gets set on the object you set it on. So:

var proto = {
    name: "proto's name"
};
var obj = Object.create(proto); // `obj` is backed by `proto`
console.log(obj.name);          // "proto's name"
obj.name = "obj's name";
console.log(obj.name);          // "obj's name"

The purpose of prototypes is reuse, and so it's no surprise that an object can be the prototype of several other objects:

var proto = {
    name: "proto's name"
};
var a = Object.create(proto);   // `a` is backed by `proto`
var b = Object.create(proto);   // `b` is also backed by `proto`
console.log(a.name);            // "proto's name"
console.log(b.name);            // "proto's name"
a.name = "a's name";
console.log(a.name);            // "a's name"
console.log(b.name);            // "proto's name"

Prototype objects are normal objects; we can change them:

var proto = {
    name: "proto's name"
};
var obj = Object.create(proto);
console.log(obj.name);          // "proto's name"
proto.name = "updated";
console.log(obj.name);          // "updated"

Since obj doesn't have its own name property, each time we access it, the JavaScript engine goes and looks at its prototype.

The new operator automatically assign a prototype to the objects it creates: It uses the object that the function's prototype property has on it. So:

function Person(name) {
    this.name = name;
}
Person.prototype.sayName = function() {
    console.log("My name is " + this.name);
};
var p = new Person("Fred"); // Creates an object backed by Person.prototype,
                            // then calls Person with this referring to the
                            // object
p.sayName();                // "My name is Fred";

Finally: Since prototype objects are normal objects, they also can have prototypes:

var rootProto = {
    name: "root proto's name"
};
var middleProto = Object.create(rootProto);
middleProto.middleProp = "middle property";
var obj = Object.create(middleProto);
console.log(obj.name);       // "root proto's name"
console.log(obj.middleProp); // "middle property"

For name, the JavaScript engine looks at obj, doesn't see a name property, and so looks at middleProto. It doesn't see a name property there, either, so it looks at rootProto. It finds it there, so it uses it.

Point of confusion: A lot of people are confused by the fact that the property on constructor functions is called prototype and think that somehow it's the prototype of the function. It isn't. It's just a normal property on function objects (functions are objects and can have properties). The only way it's special is that new uses it when you call the function via new. Non-function objects don't have a prototype property, they're prototype isn't a normal property, it's an internal thing. You can get an object's prototype by passing it into Object.getPrototypeOf:

var proto = {/*...*/};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
like image 199
T.J. Crowder Avatar answered Sep 19 '22 07:09

T.J. Crowder