Names for different Javascript Object Notation - javascript

Is there a name for describing the different ways you can define an object in Javascript?
There is this method which is more 'class-like' :
function MyObject() {
this.aMethod= new function(){
};
this.anotherMethod = new function(){
};
}
And this other technique which is more 'dynamic'.
MyObject = new Object();
MyObject.aMethod= new function(){
};
MyObject.anotherMethod = new function(){
};
I have been using both of these techniques in various ways, and i understand the benefits of each, but for the life of me, I don't have any idea how to call these two techniques when discussing this with colleauges.
Do these techniques have names?

In the first case MyObject is a constructor function, since it is supposed to be called with new:
var obj = new MyObject();
In the second case, MyObject is just an object and you assign properties to it. It does not have a special name.
Note that in both cases MyObject has different values. MyObject in the second case is equivalent to obj.
A third way is to use an object initilizer or "object literal":
var obj = {
aMethod: function(){},
anotherMethod: function(){}
};

Your first example is an Object Constructor, while the second is simply adding public methods as properties to an object. As a side note, for an even more "class-like" behavior take a look at the module pattern:
var MyObject = (function() {
var privateStaticVariable = 0;
var my = function() {
var self = this;
var privateInstanceVariable = 0;
function privateInstanceMethod() {
}
self.publicInstanceVariable = 0;
self.publicInstanceMethod = function() {
};
};
function privateStaticMethod() {
};
return my;
});

Related

Javascript object definition

Out the following two ways, which format for defining object is good considering performance and usage:
//Object created with public members defined using this.
var object1 = function () {
var private_i = null;
this.public_j = null;
//public function
this.public_func = function () {
}
}
OR
//Object created with public members defined using return patterns.
var object2 = function () {
var private_i = null,
public_j = null,
//private function will be exposed from return statement.
_public_func = function () {
};
return {
public_func : _public_func
};
}
The difference between the two relates to inheritance and usage. Your object2 always creates objects directly backed by Object.prototype and doesn't require use of the new keyword; your object1 creates object backed by object1.prototype (which is in turn backed by Object.prototype) and does require use of new.
Neither is really "better" in any objective way, they are just two different ways of using JavaScript, which will have fundamentally the same performance. The first one is much more common, the second one is advocated by a small but vocal minority within the JavaScript community.
The object1 example is more typically written like this:
function Object1() {
var private_i = null;
this.public_j = null;
//public function
this.public_func = function () {
};
}
Note that the first letter in such functions is capitalized (by overwhelming convention).
The prototype thing comes into it if you're going to have functions that don't need access to private_i: You could put those on the object that will be assigned to new objects created via new Object1 like so:
function Object1() {
var private_i = null;
this.public_j = null;
//public function
this.public_func = function () {
};
}
Object1.prototype.someOtherFunction = function() {
// Doesn't use `private_i`
};
You can also use prototypes with your object2, like so:
//Object created with public members defined using return patterns.
var object2Prototype = {
someOtherFunction: function() {
// Doesn't need private_i
};
};
var object2 = function () {
var private_i = null,
public_j = null,
//private function will be exposed from return statement.
_public_func = function () {
};
var obj = Object.create(object2Prototype);
obj.public_func = _public_func;
return obj;
};

Adding methods to an JavaScript object

I could create an object with some methods, and later add a property to it as follows:
var myObj = (function () {
var my = {};
my.method1=function(){}
my.method2=function(){}
my.method3=function(){}
return my;
}());
myObj.myProperty=123;
How could I create the object first and add a property, and then later add the methods afterwards?
myObj={};
myObj.myProperty=123;
//How do I add the above methods to myObj?
I guess there are two solutions:
Merge the objects:
var myObj = {...};
// ...
var objWithMethods = (function() { ... }());
Object.assign(myObj, objWithMethods);
(Object.assign is an ES6 methods. A polyfill can be found in the link, libraries often also provide a method with similar behavior).
Pass the object the methods should be assigned to as argument:
var myObj = {};
myObj = (function (obj) {
var my = obj || {};
my.method1=function(){}
my.method2=function(){}
my.method3=function(){}
return my;
}(myObj));
You can do an extend operation using an existing object
var myObj = {...}
var myAdditionalMethods = { someMethod : function(){ } }
//extend the object
for(var i in myAdditionalMethods)
if(!myObj.hasOwnProperty(i))
myObj[i] = myAdditionalMethods[i];
there are a lot of libraries that have this functionality built in, but that is how you would do it without one
Even prototype can add the functions to original object.
var myObj = function() {
this.myProperty = 123;
}
myObj.prototype.method1 = function method1() {
alert("method1")
}
myObj.prototype.method2 = function method2() {
alert("method2")
}
var newObj = new myObj();
newObj.method1();
newObj.method2();
console.log(newObj)

function object inheritance using jquery's extend

I'm trying to simulate inheritance using jquery extend but as far as I could test, it works only with objects.
What I'm trying to accomplish is:
var baseDefinition = function() {
var self = this;
self.calc1 = function() {
return "something1";
}
self.calc2 = function() {
return "something2";
}
self.myObject = {
propA = 100;
propB = 200;
};
}
var derivedDefinition = function() {
var self = this;
self.calc2 = function() {
return "something different from base";
}
self.myObject = {
propB = 400;
};
}
var instance = $.extend(true, {}, baseDefinition, derivedDefinition);
So I would hope to create a new instance from base definition where the derived definitions would be applied to the base ones but neither definitions would be "touched". Is it possible?
I was hoping to avoid any prototype so basicaly I would like to call instance.calc1 or instance.calc2 without knowing wether it was overriten or not.
Edit:
In my example I didn't include any object properties which was what led me to use jquery's extend function. Although both answers solve inner functions "inheritance", it doesn't (obviously) merge object properties like extend does. As a possible solution I'm thinking after I create my instance to loop through the properties of the instance and apply jquery's extend on them. Although this seems inefficient to me, I don't know if you can advise me on another course of action.
JQuery extend does not create an inheritance hierarchy, so changes you make to base definition AFTER you extend would not be reflected in derived definition. Here's how you can extend the base definition in a way that does reflect later changes down the inheritance hierarchy using Javascript prototypal inheritance:
var baseDefinition = function() {};
baseDefinition.prototype.calc1 = function() {
return "something1";
};
baseDefinition.prototype.calc2 = function() {
return "something2";
};
var derivedDefinition = function() {};
derivedDefinition.prototype = Object.create(baseDefinition.prototype);
derivedDefinition.prototype.calc2 = function() {
return "something different from base";
};
var instance = new derivedDefinition();
instance.calc1(); // something1
instance.calc2(); // something different from base
$.extend only works on already existing objects, not on function which will instantiate objects in the (far?) future:
var instance = $.extend(true, {}, new baseDefinition(), new derivedDefinition());
However, you could of course design an extend function that works for constructors and that returns a function:
function extendConstr() {
var fns = arguments;
return function newConstr(){
var self = {};
for (var i=0; i<fns.length; i++)
fns[i].apply(self, arguments);
return self;
}
}
var extendedFunction = extendConstr(baseDefinition, derivedDefinition);
var instance = extendedFunction();
console.log(instance); // has `calc1` and overwritten `calc2`
Btw, without an extend function you could've done that already manually in the derived constructor:
function derivedDefinition() {
baseDefinition.call(this/*, arguments */);
this.calc2 = function() {
return "something different from base";
}
}
console.log(new derivedDefinition) // has a `calc1` as well

Javascript: Calling object methods within that object

What is the best design pattern for achieving the following (which doesn't work)?
var obj = (function() {
// code defining private variables and methods
var _obj = {
property: value,
method1: function() {
// do stuff
},
method2: function() {
// use property
var prop = _obj.property; // obviously doesn't work
// call method1
obj.method1(); // "obj" not finished being defined yet!
}
};
// obviously now I could do...
var prop = _obj.property;
return _obj;
})();
// and I could now do...
obj.method1();
A variation which I think should work is
var obj = (function() {
var property = value,
method1 = function() {
// do stuff
},
method2 = function() {
// use property
var prop = property;
// call method1
method1();
},
_obj = {
property: property,
method1: method1,
method2: method2
};
return _obj;
})();
Similarly, how does it work for objects meant to be created with the new operator? Within the constructor function itself you can write this.method(). But what if you want to keep the constructor small, only defining those things which will likely be customized upon creation, and then defining the rest in the prototype? (This seems to be the common pattern.) Can the properties / methods within the prototype interact in any way?
var MyObj = function(name) {
this.name = name;
};
var obj = new MyObj('Bob');
MyObj.prototype = {
called_often: function() {
// lots more code than just the following
return document.getElementById('someID').value;
},
global_default: 'value', // can be changed, so need to pull value when run
does_stuff: function(value) {
var str = global_default + value, // can't access global_default on its own
input = MyObj.called_often(), // doesn't work; MyObj.prototype.called_often() DOES
name = this.name; // 'this' used in the prototype doesn't work
// even within a created object
return name + input + str;
}
};
I'm sure there's better ways to achieve my result whenever I run into this problem. This code isn't situation specific and just illustrates the general problem. So you won't be able to give me an alternative for those specific situations I run into. But maybe you can help my overall thinking.
Well, from your first example:
var _obj = {
property: value,
method1: function() {
// do stuff
},
method2: function() {
// use property
var prop = this.property;
// call method1
this.method1();
}
};
That's what the this value is for.
Now, what you cannot do is refer to a property of an "under construction" object from elsewhere in the object literal syntax. (It's hard to give an example because it's just not syntactically possible.) In cases where you want to do that, you do need one or more separate assignment statements.
Guess what? You are making simple stuff complex. Pointy's answer is good, but the prototype way is better for several reasons. That's why I am describing (rather, making corrections in) the last method. Check this fiddle.
var MyObj = function(name) {
this.name = name;
};
MyObj.prototype = {
called_often: function() {
// lots more code than just the following
return 'VALUE'; //document.getElementById('someID').value;
},
global_default: 'value', // can be changed, so need to pull value when run
does_stuff: function(value) {
var str = this.global_default + value, // can't access global_default on its own
input = this.called_often(), // doesn't work; MyObj.prototype.called_often() DOES
name = this.name; // 'this' used in the prototype doesn't work
// even within a created object
return name + input + str;
}
};
var obj = new MyObj('Bob');

Obj.apply(Obj): is it safe and performant?

I came up with a simple design pattern that was inspired by several other design patterns. Its main purpose is to have private methods (instead of all global), methods visually nested and grouped within an object, and having "self" as an available variable to access the scope, which is really useful when using calling functions with a callback parameter.
It seems to work fine, but is it safe (performance - and scope-wise) to do Obj.apply(Obj);?
The code:
function Obj() {
var self = this;
var privateFunc = function() {
console.log('private');
self.otherPublic();
};
self.publicFunc = function() {
console.log('pub1ic');
privateFunc();
};
self.otherPublic = function() {
console.log('pub2');
};
} Obj.apply(Obj);
I call it like this:
Obj.publicFunc();
Totally pointless brother. What you're doing by Obj.apply(Obj); is taking the function Obj, and adding to it those methods, in an unintuitive manner.
This:
var Obj = (function(){
var priv = function(){ console.log('2'); },
privVar = 6;
return {
pub1: function(){ console.log('1'); },
pub2: function(){ priv(); }
};
})();
Does the same thing, although better. I say better because (1) it's intuitive, and (2) Obj is now a simple javascript object (typeof Obj === 'object') whereas your Obj is a function with properties augmented (typeof Obj === 'function').
If you want a reference to self it's not hard (although it seems unnecessary), just create the object which will be returned at the top of the function, and augment the public methods, either at the end, or as you make them...
It's safe, but pointless.
Also, note that these methods won't scale well, because for each instance of Obj we create each function is recreated, which is memory-wise wasteful. This pattern above is fine because we created it with an anonymous function, so by definition there can only be one instance, although for types you need to instantiate multiple times the prototype should be used.
Don't be scared of it, it's there to be helpful.
UPDATE:
var Obj = (function(){
var priv = function(){ pub2(); },
privVar = 6,
pub1 = function(){ priv(); },
pub2 = function(){ console.log('1'); };
return {
pub1: pub1,
pub2: pub2
};
})();
Obj.pub1();
Notice that I call a public function, which calls a private function, which calls a public function - no special binding, no object reference.
UPDATE 2:
var Obj = (function(){
var public = {},
priv = function(){ public.pub2(); },
privVar = 6;
public.pub1 = function(){ priv(); },
public.pub2 = function(){ console.log('1'); };
return public;
})();
Obj.pub1();

Categories

Resources