Reputation: 3243
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.
Upvotes: 33
Views: 49817
Reputation: 766
I have been working around with JS a bit and thought of posting some answer, I hope it helps someone else too:
1) Object Literal : You literary written out the object while creating it
var person = {
name: ['Bob', 'Smith'],
age: 32,
gender: 'male',
interests: ['music', 'skiing'],
bio: function() {
alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
},
greeting: function() {
alert('Hi! I\'m ' + this.name[0] + '.');
}
};
Usage : When you want to transfer data to server
2) Constructor function: You use constructor function when you want to create multiple objects of same falvour.
function Vehicle(name, maker) {
this.name = name;// Every function while executing has a reference
this.maker = maker;// to its current execution context called as this
}
let car1 = new Vehicle(’Fiesta’, 'Ford’);// New keyword with function turns function call into constructor call
let car2 = new Vehicle(’Santa Fe’, 'Hyundai’);
console.log(car1.name); //Output: Fiesta
console.log(car2.name); //Output: Santa Fe
3) Create Javascript object with create Method
Object.create() allows to create objects with more attribute options like value, configurable, enumerable and writable . Creates a new object extending the prototype object passed as paramtere
let car = Object.create(Object.prototype,{
name:{
value: 'Fiesta',
configurable: true,
writable: true,
enumerable: false
},
maker:{
value: 'Ford',
configurable: true,
writable: true,
enumerable: true
}});
console.log(car.name) //Output: Fiesta
Prototype: Every single object is built by a constructor function. Constructor function make the object linked to its own prototype Prototype is the arbitrary link between the constructor and the object.
4) Create Javascript using ES6 classes
class Vehicle {
constructor(name, maker, engine) {
this.name = name;
this.maker = maker;
this.engine = engine;
}
}
let bike1 = new Vehicle('Hayabusa', 'Suzuki', '1340cc');
let bike2 = new Vehicle('Ninja', 'Kawasaki', '998cc');
console.log(bike1.name); //Output: Hayabusa
console.log(bike2.maker); //Output: Kawasaki
5) Using Object constructor
var d = new Object();
Best way to create empty objects.
Note : I have compiled taken most of the contents from this link https://codeburst.io/various-ways-to-create-javascript-object-9563c6887a47
Upvotes: 1
Reputation: 362
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";
};
Upvotes: 33
Reputation: 3577
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.
Upvotes: 3
Reputation: 12197
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.
Upvotes: 11
Reputation: 26474
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)
Upvotes: 4
Reputation: 234795
There isn't a whole lot of difference between approaches 2 and 3 for one-off objects. (If you were to name the function used in approach 2, you would have defined a reusable constructor.) My impression is that approach 3 is more commonly used for these situations, but I don't see a whole lot of difference between them.
It should be noted that both approaches 2 and 3 can take arguments:
var approach2Obj = new function(formalArg) {
var privateProp = ...;
this.publicProp = ...;
// more constructor logic
)(actualArg);
var approach3Obj = (function(formalArg) {
var privateProp = ...;
// more creation logic
return {
publicProp : ...;
};
}(actualArg));
P.S. As @Alexey Lebedev points out in his answer, one difference between the two (perhaps the only one) is that approach2Obj.constructor
and approach3Obj.constructor
will be different. approach3Obj.constructor
will be identically Object
, while approach2Obj.constructor
will be the anonymous function.
Upvotes: 0
Reputation: 5253
Your question should be 2 Approaches because Approach 3 is exactly like Approach 1 only the way to create that is by self execute function.
About the difference when you make an object like Approach 1 you can think about it like an object with only static function like in java. so it's always alive and you don't make instance out of it (similar to singleton) - so when you make this object:
var obj = {
prop: value,
func: function(){
alert(this.prop);
}
};
You can call it immediately:
obj.prop = 'something else';
obj.func();
Approach 2 (without the new like the comment you have got) is a classical object which you can create instances - make inherit (with js "tricks") and so on:
function Person(firstName,lastName){ // or var Person = function(...
this.firstName = firstName;
this.lastName= lastName;
this.getFullName = function(){
return this.firstName + ' ' + this.lastName;
}
}
//use
var person1 = new Person('yair','lapid');
var person2 = new Person('Naftali','Bennet');
you can put it in an array etc...
var arr = [person1,person2, new Person('shelly','yekimovits')];
Upvotes: 1
Reputation: 49909
Approach 1
This is a single object, no class and you can't define more easy if it's complex
var obj = {
prop: value
}
Approach 2
A non anonymous function. It will create an object out of a 'class', normalle the function is saved as a class name and can create multiple objects of the same type easily like below:
var Bycicle= function() {
var prop1 = value1;
this.prop2 = value2;
}
var obj1 = new Bycicle(),
obj2 = new Bycicle();
Approach 3
An anonymous function, variables from outside the function can not interfere with variables inside the function:
var a = 10;
var obj = (function() {
alert(a); // Alerts undefined
var prop1 = value1;
alert(prop1); // alerts the value of value1
return {
prop2: value2;
}
})(); // Within the () you can pass arguments to the anonymous function.
More about anonymous functions: http://helephant.com/2008/08/23/javascript-anonymous-functions/
Other approaches
There also is an Object.create()
and a new Object()
to create new objects, which both are the same as Approach 1.
Conclusion
In the end, the object will always be the same except for the 3th one, because it's anonymous.
Upvotes: 2
Reputation: 740
In order to understand approach 2, the reader needs to know some quite technical things about the way the new keyword works. Specifically that it will actually call the anonymous function as a constructor, rather than instantiate a new function object and dump it in the obj variable.
In order to understand approach 3, the reader just needs to understand the IIFE pattern. That pattern has become very common in javascript code over the past two years, and that is probably why that version is more commonly used.
Both versions are used to produce encapsulation, and both versions require knowledge of a complex language feature to understand. However the language feature required in approach three is more commonly known than the language feature required to understand approach two. Which is why approach three is more commonly used in the wild.
Upvotes: 0