Why does JavaScript have different declarations for the same behavior? - javascript

Why should I declare
var foo = {}
instead of
var foo = new Object();
in JavaScript if they are similar?
Does the same applies to
foo[0].bar = new Function(){ "return hello"};
as in in
foo[0].bar = function(){return "hello"};
?
Is it an efficiency matter? Does it make difference?

I remember reading the following from w3fools.com:
personObj=new Object();
This is a bad and unnecessary use of the new keyword. They should be
using and advocating the object literal syntax ({}) for creating new
objects.
It doesn't say why, only that we should.

Actually
var foo = {}
and
var foo = new Object();
does the same thing (both expressions create an empty Object) but it's better to use shorter version (object literal), it takes less space time to write and another thing that using object literal you can create and assign values/properties to an Object as follows
person = {
property1 : "Hello"
};
but using new Object() you need to create it first and then assign values/properties as follows
person = new Object();
person.property1 = "Hello";
In your second example (function vs new function) there is a difference because new Function is slower and you can take a look at this test here.

No there isn't any efficiency increase or decrease, its just shorthand like using ? : for if/else..
I always use shorthand {} but if you are going to have a beginner reading your code you may want to use new Object().

The only times it might matter is if your writing a program that generates such javascript dynamically ... or your writing for a certain teacher in college who seems to have a certain standard that doesn't quite make sense at times.

The new Function() constructor doesn't really work that way.
It's called like:
var myFunc = new Function("param1", "param2", "message", "/*function-body-as-a-string*/ console.log(message); return param1 + \"=\" + param2;");
ie: really dumb, error-prone, stupid-slow (uses eval) and a security-hole.
Don't use it.

Related

How to get name of variable/object that has been pushed into an array? [duplicate]

Let's say I instantiate an object in Javascript like this:
var myObj = new someObject();
Now, is it possible to obtain the var object's name as string 'myObj' from within one of the class methods?
Additional details (edited):
The reason why I would like to get the name of the variable holding reference to the object is that my new myObj would create a new clickable DIV on the page that would need to call a function myObj.someFunction(). As I insert the new DIV I need to know the name of the variable holding reference to the object. Is there maybe a better way of doing this?
You are right, sorry for the mixup in terminology.
The reason why I would like to get the name of the variable holding reference to the object is that my new myObj would create a new clickable DIV on the page that would need to call a function myObj.someFunction(). As I insert the new DIV I need to know the name of the variable holding reference to the object. Is there maybe a better way of doing this?
Shog9 is right that this doesn't make all that much sense to ask, since an object could be referred to by multiple variables. If you don't really care about that, and all you want is to find the name of one of the global variables that refers to that object, you could do the following hack:
function myClass() {
this.myName = function () {
// search through the global object for a name that resolves to this object
for (var name in this.global)
if (this.global[name] == this)
return name
}
}
// store the global object, which can be referred to as this at the top level, in a
// property on our prototype, so we can refer to it in our object's methods
myClass.prototype.global = this
// create a global variable referring to an object
var myVar = new myClass()
myVar.myName() // returns "myVar"
Note that this is an ugly hack, and should not be used in production code. If there is more than one variable referring to an object, you can't tell which one you'll get. It will only search the global variables, so it won't work if a variable is local to a function. In general, if you need to name something, you should pass the name in to the constructor when you create it.
edit: To respond to your clarification, if you need to be able to refer to something from an event handler, you shouldn't be referring to it by name, but instead add a function that refers to the object directly. Here's a quick example that I whipped up that shows something similar, I think, to what you're trying to do:
function myConstructor () {
this.count = 0
this.clickme = function () {
this.count += 1
alert(this.count)
}
var newDiv = document.createElement("div")
var contents = document.createTextNode("Click me!")
// This is the crucial part. We don't construct an onclick handler by creating a
// string, but instead we pass in a function that does what we want. In order to
// refer to the object, we can't use this directly (since that will refer to the
// div when running event handler), but we create an anonymous function with an
// argument and pass this in as that argument.
newDiv.onclick = (function (obj) {
return function () {
obj.clickme()
}
})(this)
newDiv.appendChild(contents)
document.getElementById("frobnozzle").appendChild(newDiv)
}
window.onload = function () {
var myVar = new myConstructor()
}
Short answer: No. myObj isn't the name of the object, it's the name of a variable holding a reference to the object - you could have any number of other variables holding a reference to the same object.
Now, if it's your program, then you make the rules: if you want to say that any given object will only be referenced by one variable, ever, and diligently enforce that in your code, then just set a property on the object with the name of the variable.
That said, i doubt what you're asking for is actually what you really want. Maybe describe your problem in a bit more detail...?
Pedantry: JavaScript doesn't have classes. someObject is a constructor function. Given a reference to an object, you can obtain a reference to the function that created it using the constructor property.
In response to the additional details you've provided:
The answer you're looking for can be found here: JavaScript Callback Scope (and in response to numerous other questions on SO - it's a common point of confusion for those new to JS). You just need to wrap the call to the object member in a closure that preserves access to the context object.
You can do it converting by the constructor to a string using .toString() :
function getObjectClass(obj){
if (typeof obj != "object" || obj === null) return false;
else return /(\w+)\(/.exec(obj.constructor.toString())[1];}
You might be able to achieve your goal by using it in a function, and then examining the function's source with toString():
var whatsMyName;
// Just do something with the whatsMyName variable, no matter what
function func() {var v = whatsMyName;}
// Now that we're using whatsMyName in a function, we could get the source code of the function as a string:
var source = func.toString();
// Then extract the variable name from the function source:
var result = /var v = (.[^;]*)/.exec(source);
alert(result[1]); // Should alert 'whatsMyName';
If you don't want to use a function constructor like in Brian's answer you can use Object.create() instead:-
var myVar = {
count: 0
}
myVar.init = function(n) {
this.count = n
this.newDiv()
}
myVar.newDiv = function() {
var newDiv = document.createElement("div")
var contents = document.createTextNode("Click me!")
var func = myVar.func(this)
newDiv.addEventListener ?
newDiv.addEventListener('click', func, false) :
newDiv.attachEvent('onclick', func)
newDiv.appendChild(contents)
document.getElementsByTagName("body")[0].appendChild(newDiv)
}
myVar.func = function (thys) {
return function() {
thys.clickme()
}
}
myVar.clickme = function () {
this.count += 1
alert(this.count)
}
myVar.init(2)
var myVar1 = Object.create(myVar)
myVar1.init(55)
var myVar2 = Object.create(myVar)
myVar2.init(150)
// etc
Strangely, I couldn't get the above to work using newDiv.onClick, but it works with newDiv.addEventListener / newDiv.attachEvent.
Since Object.create is newish, include the following code from Douglas Crockford for older browsers, including IE8.
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o
return new F()
}
}
As a more elementary situation it would be nice IF this had a property that could reference it's referring variable (heads or tails) but unfortunately it only references the instantiation of the new coinSide object.
javascript: /* it would be nice but ... a solution NOT! */
function coinSide(){this.ref=this};
/* can .ref be set so as to identify it's referring variable? (heads or tails) */
heads = new coinSide();
tails = new coinSide();
toss = Math.random()<0.5 ? heads : tails;
alert(toss.ref);
alert(["FF's Gecko engine shows:\n\ntoss.toSource() is ", toss.toSource()])
which always displays
[object Object]
and Firefox's Gecko engine shows:
toss.toSource() is ,#1={ref:#1#}
Of course, in this example, to resolve #1, and hence toss, it's simple enough to test toss==heads and toss==tails. This question, which is really asking if javascript has a call-by-name mechanism, motivates consideration of the counterpart, is there a call-by-value mechanism to determine the ACTUAL value of a variable? The example demonstrates that the "values" of both heads and tails are identical, yet alert(heads==tails) is false.
The self-reference can be coerced as follows:
(avoiding the object space hunt and possible ambiguities as noted in the How to get class object's name as a string in Javascript? solution)
javascript:
function assign(n,v){ eval( n +"="+ v ); eval( n +".ref='"+ n +"'" ) }
function coinSide(){};
assign("heads", "new coinSide()");
assign("tails", "new coinSide()");
toss = Math.random()<0.5 ? heads : tails;
alert(toss.ref);
to display heads or tails.
It is perhaps an anathema to the essence of Javascript's language design, as an interpreted prototyping functional language, to have such capabilities as primitives.
A final consideration:
javascript:
item=new Object(); refName="item"; deferAgain="refName";
alert([deferAgain,eval(deferAgain),eval(eval(deferAgain))].join('\n'));
so, as stipulated ...
javascript:
function bindDIV(objName){
return eval( objName +'=new someObject("'+objName+'")' )
};
function someObject(objName){
this.div="\n<DIV onclick='window.opener."+ /* window.opener - hiccup!! */
objName+
".someFunction()'>clickable DIV</DIV>\n";
this.someFunction=function(){alert(['my variable object name is ',objName])}
};
with(window.open('','test').document){ /* see above hiccup */
write('<html>'+
bindDIV('DIVobj1').div+
bindDIV('DIV2').div+
(alias=bindDIV('multiply')).div+
'an aliased DIV clone'+multiply.div+
'</html>');
close();
};
void (0);
Is there a better way ... ?
"better" as in easier? Easier to program? Easier to understand? Easier as in faster execution? Or is it as in "... and now for something completely different"?
Immediately after the object is instantiatd, you can attach a property, say name, to the object and assign the string value you expect to it:
var myObj = new someClass();
myObj.name="myObj";
document.write(myObj.name);
Alternatively, the assignment can be made inside the codes of the class, i.e.
var someClass = function(P)
{ this.name=P;
// rest of the class definition...
};
var myObj = new someClass("myObj");
document.write(myObj.name);
Some time ago, I used this.
Perhaps you could try:
+function(){
var my_var = function get_this_name(){
alert("I " + this.init());
};
my_var.prototype.init = function(){
return my_var.name;
}
new my_var();
}();
Pop an Alert: "I get_this_name".
This is pretty old, but I ran across this question via Google, so perhaps this solution might be useful to others.
function GetObjectName(myObject){
var objectName=JSON.stringify(myObject).match(/"(.*?)"/)[1];
return objectName;
}
It just uses the browser's JSON parser and regex without cluttering up the DOM or your object too much.

What is the functional difference between these two different Module pattern syntaxes

I see this syntax everywhere:
var mod = (function(){
var pvtvar;
var pvtfunc = function(){};
//return an object literal
return {
pubvar : 'whatever',
pubfunc : function(){}
};
}());
I recently came across this syntax:
//first create empty object
var mod = {};
(function(mod){
var pvtvar;
var pvtfunc = function(){};
//modify the mod object argument
mod.pubvar = 'whatever';
mod.pubfunc = function(){};
}(mod)); //pass object to IIFE
I know that they both work, and I think I understand completely why, I just want to make sure I'm not missing anything...Given identical members you end up with identical objects, it's just that in the second example mod references an empty object within the global scope for a fraction of a second, while in the first example mod only ever references the complete object once its value is returned by the IIFE.
So, am I correct in thinking that the only difference is the (very small) amount of time that the second object lives as an empty object?
And, my follow up question: do you use the second syntax, and why?
You're right. In your example, the first syntax is cleaner and more readable.
You use the second syntax when you want to pass along something more than an empty object into the module and get an augmented object in return.

Getting the name of a variable from within the variable. (JS) [duplicate]

Let's say I instantiate an object in Javascript like this:
var myObj = new someObject();
Now, is it possible to obtain the var object's name as string 'myObj' from within one of the class methods?
Additional details (edited):
The reason why I would like to get the name of the variable holding reference to the object is that my new myObj would create a new clickable DIV on the page that would need to call a function myObj.someFunction(). As I insert the new DIV I need to know the name of the variable holding reference to the object. Is there maybe a better way of doing this?
You are right, sorry for the mixup in terminology.
The reason why I would like to get the name of the variable holding reference to the object is that my new myObj would create a new clickable DIV on the page that would need to call a function myObj.someFunction(). As I insert the new DIV I need to know the name of the variable holding reference to the object. Is there maybe a better way of doing this?
Shog9 is right that this doesn't make all that much sense to ask, since an object could be referred to by multiple variables. If you don't really care about that, and all you want is to find the name of one of the global variables that refers to that object, you could do the following hack:
function myClass() {
this.myName = function () {
// search through the global object for a name that resolves to this object
for (var name in this.global)
if (this.global[name] == this)
return name
}
}
// store the global object, which can be referred to as this at the top level, in a
// property on our prototype, so we can refer to it in our object's methods
myClass.prototype.global = this
// create a global variable referring to an object
var myVar = new myClass()
myVar.myName() // returns "myVar"
Note that this is an ugly hack, and should not be used in production code. If there is more than one variable referring to an object, you can't tell which one you'll get. It will only search the global variables, so it won't work if a variable is local to a function. In general, if you need to name something, you should pass the name in to the constructor when you create it.
edit: To respond to your clarification, if you need to be able to refer to something from an event handler, you shouldn't be referring to it by name, but instead add a function that refers to the object directly. Here's a quick example that I whipped up that shows something similar, I think, to what you're trying to do:
function myConstructor () {
this.count = 0
this.clickme = function () {
this.count += 1
alert(this.count)
}
var newDiv = document.createElement("div")
var contents = document.createTextNode("Click me!")
// This is the crucial part. We don't construct an onclick handler by creating a
// string, but instead we pass in a function that does what we want. In order to
// refer to the object, we can't use this directly (since that will refer to the
// div when running event handler), but we create an anonymous function with an
// argument and pass this in as that argument.
newDiv.onclick = (function (obj) {
return function () {
obj.clickme()
}
})(this)
newDiv.appendChild(contents)
document.getElementById("frobnozzle").appendChild(newDiv)
}
window.onload = function () {
var myVar = new myConstructor()
}
Short answer: No. myObj isn't the name of the object, it's the name of a variable holding a reference to the object - you could have any number of other variables holding a reference to the same object.
Now, if it's your program, then you make the rules: if you want to say that any given object will only be referenced by one variable, ever, and diligently enforce that in your code, then just set a property on the object with the name of the variable.
That said, i doubt what you're asking for is actually what you really want. Maybe describe your problem in a bit more detail...?
Pedantry: JavaScript doesn't have classes. someObject is a constructor function. Given a reference to an object, you can obtain a reference to the function that created it using the constructor property.
In response to the additional details you've provided:
The answer you're looking for can be found here: JavaScript Callback Scope (and in response to numerous other questions on SO - it's a common point of confusion for those new to JS). You just need to wrap the call to the object member in a closure that preserves access to the context object.
You can do it converting by the constructor to a string using .toString() :
function getObjectClass(obj){
if (typeof obj != "object" || obj === null) return false;
else return /(\w+)\(/.exec(obj.constructor.toString())[1];}
You might be able to achieve your goal by using it in a function, and then examining the function's source with toString():
var whatsMyName;
// Just do something with the whatsMyName variable, no matter what
function func() {var v = whatsMyName;}
// Now that we're using whatsMyName in a function, we could get the source code of the function as a string:
var source = func.toString();
// Then extract the variable name from the function source:
var result = /var v = (.[^;]*)/.exec(source);
alert(result[1]); // Should alert 'whatsMyName';
If you don't want to use a function constructor like in Brian's answer you can use Object.create() instead:-
var myVar = {
count: 0
}
myVar.init = function(n) {
this.count = n
this.newDiv()
}
myVar.newDiv = function() {
var newDiv = document.createElement("div")
var contents = document.createTextNode("Click me!")
var func = myVar.func(this)
newDiv.addEventListener ?
newDiv.addEventListener('click', func, false) :
newDiv.attachEvent('onclick', func)
newDiv.appendChild(contents)
document.getElementsByTagName("body")[0].appendChild(newDiv)
}
myVar.func = function (thys) {
return function() {
thys.clickme()
}
}
myVar.clickme = function () {
this.count += 1
alert(this.count)
}
myVar.init(2)
var myVar1 = Object.create(myVar)
myVar1.init(55)
var myVar2 = Object.create(myVar)
myVar2.init(150)
// etc
Strangely, I couldn't get the above to work using newDiv.onClick, but it works with newDiv.addEventListener / newDiv.attachEvent.
Since Object.create is newish, include the following code from Douglas Crockford for older browsers, including IE8.
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o
return new F()
}
}
As a more elementary situation it would be nice IF this had a property that could reference it's referring variable (heads or tails) but unfortunately it only references the instantiation of the new coinSide object.
javascript: /* it would be nice but ... a solution NOT! */
function coinSide(){this.ref=this};
/* can .ref be set so as to identify it's referring variable? (heads or tails) */
heads = new coinSide();
tails = new coinSide();
toss = Math.random()<0.5 ? heads : tails;
alert(toss.ref);
alert(["FF's Gecko engine shows:\n\ntoss.toSource() is ", toss.toSource()])
which always displays
[object Object]
and Firefox's Gecko engine shows:
toss.toSource() is ,#1={ref:#1#}
Of course, in this example, to resolve #1, and hence toss, it's simple enough to test toss==heads and toss==tails. This question, which is really asking if javascript has a call-by-name mechanism, motivates consideration of the counterpart, is there a call-by-value mechanism to determine the ACTUAL value of a variable? The example demonstrates that the "values" of both heads and tails are identical, yet alert(heads==tails) is false.
The self-reference can be coerced as follows:
(avoiding the object space hunt and possible ambiguities as noted in the How to get class object's name as a string in Javascript? solution)
javascript:
function assign(n,v){ eval( n +"="+ v ); eval( n +".ref='"+ n +"'" ) }
function coinSide(){};
assign("heads", "new coinSide()");
assign("tails", "new coinSide()");
toss = Math.random()<0.5 ? heads : tails;
alert(toss.ref);
to display heads or tails.
It is perhaps an anathema to the essence of Javascript's language design, as an interpreted prototyping functional language, to have such capabilities as primitives.
A final consideration:
javascript:
item=new Object(); refName="item"; deferAgain="refName";
alert([deferAgain,eval(deferAgain),eval(eval(deferAgain))].join('\n'));
so, as stipulated ...
javascript:
function bindDIV(objName){
return eval( objName +'=new someObject("'+objName+'")' )
};
function someObject(objName){
this.div="\n<DIV onclick='window.opener."+ /* window.opener - hiccup!! */
objName+
".someFunction()'>clickable DIV</DIV>\n";
this.someFunction=function(){alert(['my variable object name is ',objName])}
};
with(window.open('','test').document){ /* see above hiccup */
write('<html>'+
bindDIV('DIVobj1').div+
bindDIV('DIV2').div+
(alias=bindDIV('multiply')).div+
'an aliased DIV clone'+multiply.div+
'</html>');
close();
};
void (0);
Is there a better way ... ?
"better" as in easier? Easier to program? Easier to understand? Easier as in faster execution? Or is it as in "... and now for something completely different"?
Immediately after the object is instantiatd, you can attach a property, say name, to the object and assign the string value you expect to it:
var myObj = new someClass();
myObj.name="myObj";
document.write(myObj.name);
Alternatively, the assignment can be made inside the codes of the class, i.e.
var someClass = function(P)
{ this.name=P;
// rest of the class definition...
};
var myObj = new someClass("myObj");
document.write(myObj.name);
Some time ago, I used this.
Perhaps you could try:
+function(){
var my_var = function get_this_name(){
alert("I " + this.init());
};
my_var.prototype.init = function(){
return my_var.name;
}
new my_var();
}();
Pop an Alert: "I get_this_name".
This is pretty old, but I ran across this question via Google, so perhaps this solution might be useful to others.
function GetObjectName(myObject){
var objectName=JSON.stringify(myObject).match(/"(.*?)"/)[1];
return objectName;
}
It just uses the browser's JSON parser and regex without cluttering up the DOM or your object too much.

JavaScript: Why is there different object Syntax? [duplicate]

All, I found there are 3 ways to declare object in javascript.
var Waffle = {
tastes:'yummy'
};
var Waffle = function()
{
this.tastes='yummy';
};
function Waffle() {
var that = {};
that.tastes = "yummy";
return that;
}
The first way is Object literal it doesn't have a constructor.
I think the equal way to Object literal is below.
var Waffle = new Object();
Waffle.tastes = 'yummy';
(If my understanding is wrong. Please correct me.)
I want to know what the difference of these 3 ways is.
Which one is the best choice?
Thanks.
The literal notation and new Object() creates an object whose prototype is directly the Object. Also, properties and methods are attached on the instance.
/*
Object
A
| instance.__proto__
|
instance
*/
//all 3 yield the same result
var foo1 = {
bar : 'bam!'
}
var foo2 = {}
foo2.bar = 'bam!';
var foo3 = new Object();
foo3.bar = 'bam!';
The constructor approach, either the declared function or the assigned function expression approach, has an additional prototype level between the instance and the Object, which contains your prototype functions attached to the constructor's prototype. Anything attached to the constructor's prototype are shared across all instances.
/*
Object
A
| instance.__proto__.__proto__
|
constructor.prototype
A
| instance.__proto__
|
instance
*/
//these 2 are the same
//bar is attached at the instance
//function expression assigned to variable foo1
var foo1 = function(){
this.bar = 'bam!'
}
//function declaration named foo2
function foo2(){
this.bar = 'bam!'
}
//==========================================================================//
//these 2 are the same, but not the same as above
//methods live on the prototype level and are shared across instances
//function expression assigned to variable foo1
var foo1 = function(){}
//function declaration named foo2
function foo2(){}
foo1.prototype.bar = 'bam!'
foo2.prototype.bar = 'bam!'
The third approach returns a new literal. You don't get the benefits of the constructor method and prototype sharing. It's as if you just called Waffle like an ordinary function, created a literal, attached properties and methods, and returned it.
Best Choice: Depends on purpose.
Object literals:
Shorter than new Object and can attach methods/properties upon definition.
Properties/methods live on the instance, no running up the prototype chain which means faster look-up.
Unoptimized creation of objects might lead to duplicates, which waste memory. For example, creating functions per instance instead of sharing via the prototype.
Constructor:
Classical OOP style
Inheritance
Shared methods via the prototype means less memory used, as opposed to per instance methods.
Forgetting the new might have unwanted consequences, like attaching globals (if window is the context)
You can check these out in the Chrome Developer tools. Create them in the Console, and watch these expressions in the Sources tab
The first is an object literal and is the same as:
var Waffle = new Object();
Waffle.tastes = 'yummy';
which is the same as:
var Waffle = {};
Waffle.tastes = 'yummy';
but of course, their instantiations take multiple lines.
Your second and third examples are functions. Your second example is an expression, while your third example is a declaration. Here's an explanation of their differences: What is the difference between a function expression vs declaration in JavaScript?
Be careful with your second example (the expression), because in order to modify this (correctly), you need to use var waffle = new Waffle();. Since this is an expression, alternatively you could've used a declaration like:
function Waffle() {
this.tastes='yummy';
}
(to understand the main difference between that and the original, which I don't think affect many people ever, read the link I provided)
The third example is a basic function that returns a new object literal.
As for the best choice...I don't think there's a concrete, definite answer.
Your first example creates a simple, single object. You can add/change properties and methods on it. But it inherits directly from Object. I like to use this when I need one big object for holding many things, and its structure is static. To reuse this, your third example is needed.
Your second example is convenient because you can invoke a new instance, giving the effect of classic OOP...and is the one I normally use. Although the caveat is that you have to use new, otherwise the value of this will be window, which is bad. At the same time, you can modify this prototype and all instances will share it. It also gives you flexibility of having "private" variables, such as:
function Waffle() {
var testing = 0;
this.name = "A";
this.myMethod = function () {
return testing;
};
}
Your third example is similar to the second, except that you can't tap into a prototype, since you're returning an Object. It's basically using your first example, but making it reusable. It also allows for "private" variables like above, as well.
So if you're looking for a single object, use your first example. If you're looking for reusability, I'd suggest your second example, while the third is still an example. Hopefully I explained enough about each for you to determine which suits your needs.

What is the difference of 3 object declarations of javascript

All, I found there are 3 ways to declare object in javascript.
var Waffle = {
tastes:'yummy'
};
var Waffle = function()
{
this.tastes='yummy';
};
function Waffle() {
var that = {};
that.tastes = "yummy";
return that;
}
The first way is Object literal it doesn't have a constructor.
I think the equal way to Object literal is below.
var Waffle = new Object();
Waffle.tastes = 'yummy';
(If my understanding is wrong. Please correct me.)
I want to know what the difference of these 3 ways is.
Which one is the best choice?
Thanks.
The literal notation and new Object() creates an object whose prototype is directly the Object. Also, properties and methods are attached on the instance.
/*
Object
A
| instance.__proto__
|
instance
*/
//all 3 yield the same result
var foo1 = {
bar : 'bam!'
}
var foo2 = {}
foo2.bar = 'bam!';
var foo3 = new Object();
foo3.bar = 'bam!';
The constructor approach, either the declared function or the assigned function expression approach, has an additional prototype level between the instance and the Object, which contains your prototype functions attached to the constructor's prototype. Anything attached to the constructor's prototype are shared across all instances.
/*
Object
A
| instance.__proto__.__proto__
|
constructor.prototype
A
| instance.__proto__
|
instance
*/
//these 2 are the same
//bar is attached at the instance
//function expression assigned to variable foo1
var foo1 = function(){
this.bar = 'bam!'
}
//function declaration named foo2
function foo2(){
this.bar = 'bam!'
}
//==========================================================================//
//these 2 are the same, but not the same as above
//methods live on the prototype level and are shared across instances
//function expression assigned to variable foo1
var foo1 = function(){}
//function declaration named foo2
function foo2(){}
foo1.prototype.bar = 'bam!'
foo2.prototype.bar = 'bam!'
The third approach returns a new literal. You don't get the benefits of the constructor method and prototype sharing. It's as if you just called Waffle like an ordinary function, created a literal, attached properties and methods, and returned it.
Best Choice: Depends on purpose.
Object literals:
Shorter than new Object and can attach methods/properties upon definition.
Properties/methods live on the instance, no running up the prototype chain which means faster look-up.
Unoptimized creation of objects might lead to duplicates, which waste memory. For example, creating functions per instance instead of sharing via the prototype.
Constructor:
Classical OOP style
Inheritance
Shared methods via the prototype means less memory used, as opposed to per instance methods.
Forgetting the new might have unwanted consequences, like attaching globals (if window is the context)
You can check these out in the Chrome Developer tools. Create them in the Console, and watch these expressions in the Sources tab
The first is an object literal and is the same as:
var Waffle = new Object();
Waffle.tastes = 'yummy';
which is the same as:
var Waffle = {};
Waffle.tastes = 'yummy';
but of course, their instantiations take multiple lines.
Your second and third examples are functions. Your second example is an expression, while your third example is a declaration. Here's an explanation of their differences: What is the difference between a function expression vs declaration in JavaScript?
Be careful with your second example (the expression), because in order to modify this (correctly), you need to use var waffle = new Waffle();. Since this is an expression, alternatively you could've used a declaration like:
function Waffle() {
this.tastes='yummy';
}
(to understand the main difference between that and the original, which I don't think affect many people ever, read the link I provided)
The third example is a basic function that returns a new object literal.
As for the best choice...I don't think there's a concrete, definite answer.
Your first example creates a simple, single object. You can add/change properties and methods on it. But it inherits directly from Object. I like to use this when I need one big object for holding many things, and its structure is static. To reuse this, your third example is needed.
Your second example is convenient because you can invoke a new instance, giving the effect of classic OOP...and is the one I normally use. Although the caveat is that you have to use new, otherwise the value of this will be window, which is bad. At the same time, you can modify this prototype and all instances will share it. It also gives you flexibility of having "private" variables, such as:
function Waffle() {
var testing = 0;
this.name = "A";
this.myMethod = function () {
return testing;
};
}
Your third example is similar to the second, except that you can't tap into a prototype, since you're returning an Object. It's basically using your first example, but making it reusable. It also allows for "private" variables like above, as well.
So if you're looking for a single object, use your first example. If you're looking for reusability, I'd suggest your second example, while the third is still an example. Hopefully I explained enough about each for you to determine which suits your needs.

Categories