99

I am getting confused over which way I should be creating an object in javascript. It seems there are at least two ways. One is to use object literal notation while the other uses construction functions. Is there an advantage of one over the other?

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
chobo
  • 31,561
  • 38
  • 123
  • 191
  • 2
    The best answer: http://stackoverflow.com/questions/4597926/creating-objects-new-object-or-object-literal-notation -- In summary, you can set up a function to create instances form literal notation as well. Doing this each instance carries all the methods, whereas with a constructor all instances refer to the prototype methods. Ie constructor has better memory performance. – Federico Dec 17 '14 at 22:40
  • If memory is not an issue object literals property access are many magnitudes faster - https://jsperf.com/module-pattern-vs-object-literal-vs-prototype/4 – Daniel Sokolowski Jul 23 '18 at 14:28

12 Answers12

133

If you don't have behaviour associated with an object (i.e. if the object is just a container for data/state), I would use an object literal.

var data = {
    foo: 42,
    bar: 43
};

Apply the KISS principle. If you don't need anything beyond a simple container of data, go with a simple literal.

If you want to add behaviour to your object, you can go with a constructor and add methods to the object during construction or give your class a prototype.

function MyData(foo, bar) {
    this.foo = foo;
    this.bar = bar;

    this.verify = function () {
        return this.foo === this.bar;
    };
}

// or:
MyData.prototype.verify = function () {
    return this.foo === this.bar;
};

A class like this also acts like a schema for your data object: You now have some sort of contract (through the constructor) what properties the object initializes/contains. A free literal is just an amorphous blob of data.

You might as well have an external verify function that acts on a plain old data object:

var data = {
    foo: 42,
    bar: 43
};

function verify(data) {
    return data.foo === data.bar;
}

However, this is not favorable with regards to encapsulation: Ideally, all the data + behaviour associated with an entity should live together.

Ates Goral
  • 137,716
  • 26
  • 137
  • 190
  • 15
    Great explanation, but what about putting functions in an object literal? I have seen this done before. Actually the post below has an example of this. – chobo Feb 01 '11 at 17:49
  • 24
    If you include the function definitions as part of the object literal, or use the `this.fn = function ...` approach in a constructor, each of your object instances will have their own copies of functions. Using the prototype approach, you attach each function once and only once: they'll be inherited by the instances through prototypal inheritance. – Ates Goral Feb 01 '11 at 21:16
  • 15
    I believe you missed an important thing. only constructor function can provide private members as well as public members (encapsulation). in the object literal - they are all public. – Royi Namir Jun 10 '15 at 06:53
  • What would be a better way to go for a game engine? I used the constructor method but my prototypes don't have access to the constructor data. – zachdyer Jun 12 '15 at 16:19
101

It essentially boils down to if you need multiple instances of your object or not; object defined with a constructor lets you have multiple instances of that object. Object literals are basically singletons with variables/methods that are all public.

// define the objects:
var objLit = {
  x: 0,
  y: 0,
  z: 0,
  add: function () {
    return this.x + this.y + this.z;
  }
};

var ObjCon = function(_x, _y, _z) {
  var x = _x; // private
  var y = _y; // private
  this.z = _z; // public
  this.add = function () {
    return x + y + this.z; // note x, y doesn't need this.
  };
};

// use the objects:
objLit.x = 3; 
objLit.y = 2; 
objLit.z = 1; 
console.log(objLit.add());    

var objConIntance = new ObjCon(5,4,3); // instantiate an objCon
console.log(objConIntance.add());
console.log((new ObjCon(7,8,9)).add()); // another instance of objCon
console.log(objConIntance.add()); // same result, not affected by previous line
ronnbot
  • 1,241
  • 1
  • 9
  • 5
9

Another way to create objects in a uniform way is to use a function that returns an object:

function makeObject() {
    var that = {
        thisIsPublic: "a public variable"
        thisIsAlsoPublic: function () {
            alert(that.thisIsPublic);
        }
    };

    var secret = "this is a private variable"

    function secretFunction() { // private method
        secret += "!"; // can manipulate private variables
        that.thisIsPublic = "foo";     
    }

    that.publicMethod = function () {
        secret += "?"; // this method can also mess with private variables
    }

    that.anotherPublicVariable = "baz";

    return that; // this is the object we've constructed
}

makeObject.static = "This can be used to add a static varaible/method";

var bar = makeObject();
bar.publicMethod(); // ok
alert(bar.thisIsPublic); // ok
bar.secretFunction(); // error!
bar.secret // error!

Since functions in JavaScript are closures we can use private variables and methods and avoid new.

From http://javascript.crockford.com/private.html on private variables in JavaScript.

JustcallmeDrago
  • 1,885
  • 1
  • 13
  • 23
7

The code below shows three methods of creating an object, Object Literal syntax, a Function Constructor and Object.create(). Object literal syntax simply creates and object on the fly and as such its __prototype__ is the Object object and it will have access to all the properties and methods of Object. Strictly from a design pattern perspective a simple Object literal should be used to store a single instance of data.

The function constructor has a special property named .prototype. This property will become the __prototype__ of any objects created by the function constructor. All properties and methods added to the .prototype property of a function constructor will be available to all objects it creates. A constructor should be used if you require multiple instances of the data or require behavior from your object. Note the function constructor is also best used when you want to simulate a private/public development pattern. Remember to put all shared methods on the .prototype so they wont be created in each object instance.

Creating objects with Object.create() utilizes an object literal as a __prototype__ for the objects created by this method. All properties and methods added to the object literal will be available to all objects created from it through true prototypal inheritance. This is my preferred method.

//Object Example

//Simple Object Literal
var mySimpleObj = {
    prop1 : "value",
    prop2 : "value"
}

// Function Constructor
function PersonObjConstr()  {
    var privateProp = "this is private";
    this.firstname = "John";
    this.lastname = "Doe";
}
PersonObjConstr.prototype.greetFullName = function()    {
    return "PersonObjConstr says: Hello " + this.firstname + 
    " " + this.lastname;
};

// Object Literal
var personObjLit = {
    firstname : "John",
    lastname: "Doe",
    greetFullName : function() {
        return "personObjLit says: Hello " + this.firstname +
        ", " + this.lastname;
    }
} 

var newVar = mySimpleObj.prop1;
var newName = new PersonObjConstr();
var newName2 = Object.create(personObjLit);
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
JOP
  • 89
  • 1
  • 1
  • 1
    Since you declared the function inside an object literal. Does that mean when you create an object using `Object.create` the function inside the literal will be unique per instance? – JohnnyQ Oct 24 '16 at 20:20
6

It depends on what you want to do. If you want to use (semi-)private variables or functions in you object, a constructor function is the way to do it. If your object only contains properties and methods, an object literal is fine.

function SomeConstructor(){
    var x = 5;
    this.multiply5 = function(i){
        return x*i;
    }
}
var myObj = new SomeConstructor;

var SomeLiteral = {
    multiply5: function(i){ return i*5; }
}

Now the method multiply5 in myObj and SomeLiteral do exactly the same thing. The only difference is that myObj uses a private variable. The latter may be usefull in some cases. Most of the times an Object literal is sufficient and a nice and clean way to create a JS-object.

resu
  • 944
  • 12
  • 21
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • What's the difference between a function and a method? I come from a c# background so to me a function is standalone and a method is just a function that is part of a class. – chobo Feb 01 '11 at 18:49
  • 1
    There's not that much difference, see for example http://www.web-source.net/javascript_tutorial/javascript_functions_methods.htm. Actually, in DOMscripting (client side js in a browser), all functions become methods of the window-object (the global namespace) I would say (you can address all 'standalone' functions as window.[somefunction]. – KooiInc Feb 03 '11 at 09:02
5

enter image description here

Do you want single instance of the object for the page -- Literal.

Do you want to just transfer data like DTO objects simple GET SET :- Literal

Do you want to create real objects with method behaviors , multiple instances - Constructor function , Follow OOP principles , inheritance :- Constructor functions.

Below is the youtube video which explains in detail what is literal , what are constructor functions and how they differ from each other.

https://www.youtube.com/watch?v=dVoAq2D3n44

Shivprasad Koirala
  • 27,644
  • 7
  • 84
  • 73
1

As mentioned in https://www.w3schools.com/js/js_object_definition.asp

Using an object literal, you both define and create , one object in one statement.

Also

Object literal only create a single object. Sometimes we like to have an object type that can be used to create many objects of one type.

Alireza Fattahi
  • 42,517
  • 14
  • 123
  • 173
0

Go with object literal, it's more consise and expands better with the introduction of initial values.

Tom
  • 43,583
  • 4
  • 41
  • 61
  • How do you create private variables in an object literal? – EhevuTov Sep 23 '13 at 10:20
  • You can't really, it's not relevant to the original question so I'm just going to give you a link: http://javascript.crockford.com/private.html – Tom Sep 23 '13 at 15:10
  • 2
    Actually, it is relevant because where there's a difference, there's a reason to use one or the other depending on certain situations; in this instance it would be whether you want private variables or not. You can create private variables in a literal by first creating a closure function in your literal, but it's a lot uglier in my opinion and hard to read. – EhevuTov Sep 23 '13 at 19:22
  • I stand corrected, my original reading of the question was that chobo was asking about how to pass variables to a constructor as in parameter list vs single object literal parameter. – Tom Sep 24 '13 at 04:16
0

The Object() constructor function is a bit slower and more verbose. As such, the recommended way to create new objects in JavaScript is to use literal notation

Udacity Object-Oriented JavaScript

techkuz
  • 3,608
  • 5
  • 34
  • 62
0

Actually, methinks, we can have private methods in object literals. Consider code below:

var myObject = {

   publicMethod: function () {
      privateMethod1();
      privateMethod2(); 
      function privateMethod1(){
          console.log('i am privateMethod1');
      } 
      function privateMethod2(){
          console.log('i am privateMethod2');
      } 
   }

}

Matter of taste, but I prefer to use object literals where it is possible.

Yuriy N.
  • 4,936
  • 2
  • 38
  • 31
0

Here is a benchmark that shows the access time for accessing properties on literals, constructors and classes. It might take a while but it shows almost every way to access properties. To me this benchmark shows literal properties access time overall are slightly slower than class and constructor properties access time. The worst performing times are from getters and setters on an object literal. Unlike getters and setters on classes and constructors which seem to be even faster than most other access times. Benchmark: https://www.measurethat.net/Benchmarks/Show/12245/0/the-grand-dictionary-property-accessor-schema Graph result on benchmark

Berend Kemper
  • 31
  • 1
  • 5
-1

// Object Literal and Object constructor

function MyData(foo, bar) {
        this.foo = foo;
        this.bar = bar;

    }
MyData.prototype.verify = function () {
        return this.foo === this.bar;
    };

//add property using prototype

var MD  = new MyData;//true.
var MD = new MyData();//true.
MD.verify// return only the function structure.
MD.verify(); //return the verify value and in this case return true coz both value is null. 
var MD1  = new MyData(1,2); // intialized the value at the starting. 
MD1.verify// return only the function structure.
MD1.verify(); // return false coz both value are not same.
MD1.verify(3,3);// return false coz this will not check this value intialized at the top 
MyData.prototype.verify = function (foo,bar) {
    return this.foo === this.bar;
};
var MD1  = new MyData(1,2);
MD1.verify();
MD1.verify(3,3);// return false coz this keyword used with foo and bar that will check parent data 
Amit kumar
  • 457
  • 6
  • 14