I have seen a few different ways to instantiate objects in javascript, wanted to know the benefits/drawbacks of the various approaches and why you would use one over the other.
Approach 1
var obj = {
prop: value,
.
.
.
}
Approach one is standard approach, nothing new :)
Approach 2
var obj = new function() {
var prop1 = value1;
var fn1 = function() {
};
.
.
.
this.prop2 = value2;
.
.
.
}();
The function approach, I wanted to compare this approach with approach 3. The function approach is primarily used for encapsulation (correct?)
Approach 3
var obj = (function() {
var prop1 = value1;
var fn1 = function() {
};
.
.
.
return {
prop2: value2,
.
.
.
}
})();
With this approach, I do not quite see the reasoning behind its usage. How does it differ from approach 2? Both can be used to encapsulate logic.
Is it so we can pass in parameters, so we can deal with any potential conflicts?? E.g jquery's $
syntax - but you can also do this with approach 2...
Thanks.
Edit:
I am aware the approach 1 and 3 are similar (in that they both return objects) however approach 3 also creates a closure. Which approach 2 also does.
That is the basis of my question really, both 2 and 3 create closures, but what is the difference between them.
You can create an object in three different ways: Using object literal. By creating instance of Object directly. By using constructor function.
JavaScript Object Methods This method returns an array with arrays of the key, value pairs. This method prevents existing properties from being removed. This method returns a property descriptor for the specified property of the specified object. This method returns all own property descriptors of a given object.
Conclusion. There are four ways to create an object in JavaScript - using object literals, using the function constructor, using the Object. create method, and using the class keyword (which is almost the same as using a function constructor).
7 ways to create objects in JavaScript :
1. Object constructor
The simplest way to create an object is to use the Object constructor: view plainprint?
var person = new Object();
person.name = "Diego";
person.getName = function(){
return this.name;
};
2. Literal notation
view plainprint?
var person = {
person.name : "Diego",
person.getName : function(){
return this.name;
}
}
3. Factory function
The Factory function allows to encapsulate and re-use the logic for creating similar objects. It leverages any of the previous constructs for this. Either: view plainprint?
var newPerson=function(name){
var result = new Object();
result.name = name;
result.getName = function(){
return this.name;
};
return result;
};
var personOne = newPerson("Diego");
var personTwo = newPerson("Gangelo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Gangelo
Or:
view plainprint?
var newPerson=function(name){
return {
person.name : name,
person.getName : function(){
return this.name;
};
};
var personOne = newPerson("Diego");
var personTwo = newPerson("Gangelo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Gangelo
4. Function Constructor
In Javascript it is possible to call any function with the new operator in front of it. Given a function F, for new F(): a new empty object X is created. X is set as context for F meaning throughout F this points to X. X is returned as result of F view plainprint?
function Person(name){
this.name = name;
this.getName = function(){
return this.name;
};
};
var personOne = new Person("Diego");
console.log(personOne.getName()); // prints Diego
console.log(personOne instanceOf Person); // prints true
console.log(personOne.constructor === Person); // prints true
console.log(personOne instanceOf Object); // prints true
5. Prototype
Functions are very special in Javascript. They are objects, they can create other objects and they automatically get a field called prototype. A prototype is a plain object with a single field, called constructor, pointing to the function itself. What makes it special is that every object created through a function inherits the function's prototype. view plainprint?
function Person(){};
Person.prototype.name = "Diego";
var personOne = new Person();
var personTwo = new Person();
console.log(personOne.constructor == Person); // prints true
console.log(personOne.name); // prints Diego
console.log(personTwo.constructor == Person); // prints true
console.log(personTwo.name); // prints Diego
6. Function/Prototype combination
The function/prototype combination, as you would imagine, takes advantage of both approaches :) view plainprint?
function Person(name){
this.name = name;
};
Person.prototype.getName = function(){
return this.name;
};
var personOne = new Person("Diego");
var personTwo = new Person("Filippo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Filippo
console.log(personOne.getName === personTwo.getName) //prints true
7. Singleton
Sometimes, you may want to make sure that only a single instance of a certain class exists. To get a Singleton in Javascript is as simple as defining and invoking the constructor at the same time: view plainprint?
var singleton = new function(){
this.name = "ApplicationName";
};
In approaches #2 and #3 the constructor
property of the resulting objects will be different.
In practice it means that the second approach allows you to instantiate more than one object using the anonymous constructor function:
x = new function() { alert(1) };
y = new x.constructor; // shows the message too
The top answer to Module pattern vs. instance of an anonymous constructor includes a quote from Douglas Crockford in which he explains why he thinks the approach #3 is better than #2.
The first and third approach are almost the same, in a way they both create an object literal, which is a direct child of Object
class. The difference between them is that in the third approach you may have some sort of encapsulation of properties:
var obj = (function() {
var prop = {};
return {
prop2: function(){ return prop };
}
})();
Performance-wise you might consider that the third approach creates closure, while the first one does not!
However in the second approach you are merely creating a new object from an anonymous class which is not a direct child of Object
class.
The correct form of the second approach is this (at least that's ecma standard):
var obj = new function() {
var prop1 = value1;
this.prop2 = value2;
}();
The difference between approach 2 and 3 is only their inheritance chain: (assuming obj2 is from 2nd approach and obj3 is from 3rd approach)
obj2.__proto__ == Object.prototype; // false
obj3.__proto__ == Object.prototype; // true
obj2 is created from an anonymous class itself:
obj2.__proto__.__proto__ == Object.prototype; // true (there's 2 level of inheritance here)
There's also:
var obj = Object.create({prop: ...});
This works by setting a prototype. It's much more efficient to use a prototype if you are going to have multiple objects sharing properties or methods.
var proto = {foo: function() {}},
obj1 = Object.create(proto),
obj2 = Object.create(proto),
obj3 = {foo: function() {}},
obj4 = {foo: function() {}};
In this example, obj1 and obj2 share a "foo" function, defined in "proto". Meanwhile, obj3 and obj4 each have their own "foo". If you are creating lots of objects with lots of properties, this can make a big difference in memory consumption and even performance.
This benefit is shared by use of the "new" keyword if you use a named function and assign properties to the function's prototype (ex: f.prototype.prop) before using new.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With