2

Learning Javascript I am finding different ways for creating objects. Seems that the way forward is using Object.create()

It's pretty hard to find a solid answer on best practises for using Object.create() as even the specific Object.create() articles seem to do things slightly different.

What I want to do is create multiple objects with their own encapsulated data.

I like to use encapsulation and what seems to work for me is something like

function Foo() {
    var message = "Hello";

    return {
        bar:bar
    }

    function bar(){ 
        return message; 
    }
}

World = (function(){ 
    var obj = Foo();
    var tank = Object.create(obj);

    return {
        baz:baz
    }

    function baz(){ 
        alert(tank.bar()); 
    }

})();

Running World.baz() works as expected but I am still not sure if I am doing this right.

All answers will be appreciated, thanks.

Aaron
  • 3,195
  • 5
  • 31
  • 49

3 Answers3

1

Generally in javascript you want to create objects like so:

var obj = {};
obj.someProperty = 'someValue';
obj.someOtherProperty = 'someOtherValue';

Or, you could use object literal notation, like this:

var obj = {
    someProperty: 'someValue',
    someOtherProperty: 'someOtherValue'
};

The Object.create function is an interesting one. Yes, it does create an empty object, but it isn't like the objects defined above. Instantiating and object with Object.create will give the new empty object inheritance up to the parameter you give the Object.create function. For instance, if we define an object as:

var actions = {
    shout: function(message){
        console.log(message.toUpperCase() + '!');
    }
}

And then create a new object with Object.create():

var newObject = Object.create(actions);  // creates a new object: newObject = {};

newObject will not contain any of it's own properties, but it will be able to access the properties of the parent actions object. After defining those object, try this out:

newObject.hasOwnProperty('shout');    // returns false
newObject.shout('Hello!');    // logs 'HELLO!!'

This example just goes to show how inheritance works from the newly created object to it's parent. This can be extremely useful, but make sure you specifically want that behavior before creating objects with Object.create-- otherwise, better be safe and use one of the two other methods above.

Hope that helps!

Edit:

Alternatively, if you're just trying to create many separate instances of the same object, you can create a constructor and invoke it with the new keyword, like this:

var Tank = function(speed, durability){
    this.speed = speed;
    this.durability = durability;
    this.location = 0;
    this.shoot = function(){
        console.log('Pew pew');
    };
    this.move = function(){
        this.location += speed;
    };
}

var myTank = new Tank(5, 15);    // creates new tank with speed 5 and durability 15,
                                 // that also has all the default properties and methods,
                                 // like location, shoot, and move.

var yourTank = new Tank(7, 12);  // instantiates a different tank that myTank, with it's
                                 // own speed and durability properties, but also has the
                                 // default location, shoot, and move properties/ methods

var enemyTank = new Tank(10, 25);// instantiates yet another, unique tank with it's own 
                                 // unique values for speed and durability, but again with
                                 // the default location, shoot, and move properties/methods
Mercury
  • 350
  • 2
  • 7
  • Won't I be able to access the object member 'someProperty' from outside the obj? – Aaron Jul 05 '14 at 19:05
  • 'someProperty' lives on the obj object. You can access it from outside that object using dot notation: obj.someProperty. In the case of properties of objects that are not functions, it doesn't make much difference that they live on that object. In the case of functions, though, quite often the object that the function lives on does make a difference in how the function behaves, particularly due to the keyword 'this'. – Mercury Jul 05 '14 at 20:01
0

I would suggest using constructors to encapsulate data. If you really need to use Object.create(), you need to create a constructor-prototype system with Object.create(). However, in any case, you're just calling .bar() from the result of Foo() in the .baz() method of World. That does not mean World should point to the result of Foo().

Object.prototype.__construct = function() {
    //This is the default constructor from any new object. We change it to change the constructor of objects as we go along. We could make no __construct method on Object.prototype because it doesn't do anything, so we're not going to call it, but we're going to define it anyway since we want all objects to have a __construct method, even if they don't define a new one on top of the default.
};
//Object.prototype is our default object. We add methods to object to change the prototype of objects as we go along.

var Foo = {}; //Any object that doesn't inherit from anything must inherit from Object.prototype. We do this by just setting it to {} (or new Object()).
//If we're going to define a new constructor, we need to call it _after_ we've defined it.
Foo.__construct = function() {
    var message = "Hello!";
    this.bar = function() {
        return message;
    }
};
Foo.__construct();
Foo.bar() //returns "Hello!"
//Note that message is encapsulated and _cannot_ be accessed through Foo itself.

var World = {}; //World _does not_ point to Foo. It simply calls a method of Foo in one of its methods.
World.__construct = function() {
    //Now, if the method of Foo we're going to call in the method of World is going to alter Foo, then we should make a copy of Foo using Object.create(). The method we're going to call isn't _actually_ going to alter Foo, but it's good practice to make a copy because it _could_ if we made it so.
    var obj = Object.create(Foo);
    //Because Foo has been constructed and obj is a copy of Foo, we don't need to construct obj. We only need to construct an object if we define a new constructor property.
    this.baz = function() {
        alert(obj.bar());
    };
};
World.__construct();
World.baz() //alerts "Hello!"
//Note that obj is encapsulated within World. obj points to Foo, but again, World _does not_ point to Foo.
Noble Mushtak
  • 1,784
  • 10
  • 22
  • 1
    Noble I originally did use new. I am being discouraged away from using new and being told to use Object.create() which is not as intuitive as new and it also giving me problems with the objects not having their own local variables which is a bridge I will cross when I get to – Aaron Jul 05 '14 at 19:14
  • Then you need to make a constructor system based off `Object.create()`. I edited my answer to show this. – Noble Mushtak Jul 05 '14 at 19:36
  • @Aaron who told you not to use new? Some examples of how and why to use constructor functions, prototype and Object.create can be found here.http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Jul 06 '14 at 01:37
0

Try this approach for creating javaScript objects that encapsulating data. As you can see each instance of Foo has its own properties and state.

    var Foo = function() {

        var Foo = function Foo(customMessage) {
            this.message = customMessage || "Hello";
        }

        Foo.prototype.message;

        Foo.prototype.bar = function(){ 
            return this.message; 
        }

        return Foo;
    }();

    var tank1 = new Foo();
    var tank2 = new Foo("Goodbye");

    alert(tank1.bar());
    alert(tank2.bar());
Rich Hildebrand
  • 1,607
  • 17
  • 15