I'm building a library that is a loading screen which allows me to call Loader.Show(), Loader.Hide() or Loader.Step() from various different documents.
I've built the library, however I do not fully understand the various ways to declare objects. Whats the difference in the following two models, and which is better?
//Example 1
var Robot = (function () {
var metal = "Steel";
return {
killAllHumans: function() {
alert(metal);
}
}
})();
Robot.killAllHumans();
//Example 2
var NonRobot = {
runState: "Normal",
run: function() {
alert(this.runState);
}
}
NonRobot.run();
I understand that both example 1 & create objects. I also understand that in Example 1, metal is a private variable. I do not know how to create a private variable in example 2. Is the only difference the scope?
This method creates a private context where you could add your own variable and do some intermediate evalations or even create private variables, such as metal
var Robot = (function () {
var metal = "Steel";
return {
killAllHumans: function() {
alert(metal);
}
}
})();
On the other hand, this version creates is an object literal:
var NonRobot = {
runState: "Normal",
run: function() {
alert(this.runState);
}
}
NonRobot.run();
runState is not a private property of NonRobot and it can be manipulated by outside forces.
In the first instance you are using an Immediately Invoked Function Expression as a constructor.
In the second, you are creating an object using an object literal.
Related
I'm currently making a tiny game structured like so:
let Game = function() {
let privateVar;
// private would be an example private variable assigned later
// Other private variables go here
return {
Engine: function() {
// More specific private variables
init: function() {
privateVar = this.sampleValue;
// Game.Engine.sampleValue doesn't help either
// Start up everything, for example, calling a Graphics method:
Game.Graphics.method1();
},
sampleValue: 10,
// Other methods
}
Graphics: Graphics()
}
}
function Graphics() {
// Visuals-specific private variables
return {
method1: function() {
console.log(privateVar);
// This would complain about the variable not being defined
}
// methods
}
}
Game.Engine.Init();
The idea is to separate the visual code from the internal code by calling the Graphics() function in the Graphics method (so I can for example build the Graphics() function in a separate file for example). However, when I do this, the Graphics method loses the private variable I declared at the beginning and assigned at the init method, and spits out Uncaught ReferenceError: private is not defined whenever it's called by some method in Graphics.
I guess one solution would be just reassigning those privates in Graphics(), but that would somewhat kill the purpose. Anyone has a better idea? Thanks in advance.
EDIT: Made the code a bit easier to understand what I'm getting at
If you want private variables your Graphics type should not access them. How about declaring public variables instead ?
Like this for instance:
let Game = function() {
this.publicVar = "value";
}
Or you can declare getters to access private fields and pass Game instance to the Graphics type. Like this :
let Game = function() {
let privateVar = "value";
this.getPrivateVar = function() {
return privateVar;
}
}
function Graphics(game) {
// ...
}
I think that you are trying to use O.O. in javascript.
Javascript is prototyped, so, the way you will use O.O. is different than usual languages. see mozilla reference
I think you should create js classes like these:
/**
* #class Game Class
*/
function Game() {
this.privateProperty;
this.engine = new Engine(); //engine object of this game
this.graphics = new Graphics(); //graphics object of this game
}
Game.prototype.oneGameMethod = function(){
};
/**
* #class Engine Class
*/
function Engine(){
this.privateProperty;
}
Engine.prototype.oneEngineMethod = function(){
};
/**
* #class Graphics class
*/
function Graphics() {
// Visuals-specific private variables
this.visualProperty;
}
Graphics.prototype.oneMethodExample = function(){
};
Than you can create an Game object and call its methods and so on:
var myGame = new Game();
When creating an object to use JS in an OO manner, is there any difference within a JS engine between (with the exception of being able to define a constructor:
var Uploader = Uploader || {};
and
var Uploader = function() {
}
and
function Uploader() {
}
Especially when later, you wish to do something along the lines of
Uploader.DOM = {
Create: function(file) {
}
};
Is it all down to personal preference? Or is there a real difference?
Objects:
var MyObj = {
myArr: [1,2,3],
find: function(/*some arguments*/) {
//some logic that finds something in this.myArr
}
}
In MyObj.find function this keyword will point to MyObj (which somewhat resembles how this works in languages those have classes). You can use this functionality to do mix-ins:
var MyObj2 = {
myArr: [4,2,6]
}
MyObj2.find = MyObj.find;
In MyObj2.find function this keyword will point to MyObj2.
Also objects support getters and setters (works on IE9+ and all good browsers):
var MyObj = {
myArr: [1,2,3],
find: function(/*some arguments*/) {
//some logic that finds something in this.myArr
},
get maxValue() {
return Math.max.apply(null, this.myArr);// maxValue is calculated on the fly
},
a_: null,
get a () {
return this.a_;
},
set a (val) {
//fire a change event, do input validation
this.a_ = val;
}
}
Now max value in the array can be accessed like this: MyObj.maxValue. I also added a property a_. It can't be named the same as its getter and setter so appended an underscore. Appending or prepending underscores is a naming convention for private variables which should not be accessed directly.
var qwe = MyObj.a // get a_
MyObj.a = 'something'; //set a_
Functions:
var u = new Uploader(); // will throw an exception
var Uploader = function() { }
Uploader is defined in runtime here. It does not exist yet when I try to instantiate it.
var u = new Uploader(); //will work
function Uploader() {}
Uploader is defined in compilation time here so it will work.
Functions can be used with revealing pattern to conceal some members. Functions don't support getters and setters but you can put objects inside functions.
function myFunc() {
function privateFunc() {};
function publicFunc() {};
var obj = {
//members, getters, setters
};
return {
publicFunc: publicFunc,
obj: obj
}
}
You can call muFunc.publicFunc() outside of myFunc because it is returned. But you can not use privateFunc outside because it is not returned.
Revealing pattern functions are not meant to be instantiated usually. This is because when you instantiate it everything inside will be copied to a new instance. So it will use up more memory than if you would add functions using prototype.
myFunc.prototype.someFunc = function() {};
Like this all instances of myFunc will share the same instance of someFunc.
Conclusion: with functions you can simulate a private access modifier but in objects the this keyword acts somewhat similar of what you'd expect in a language that have classes. But you always can use call, apply and bind to change the context (i.e. what 'this' keyword will be) of the function.
I'm developing a node.js application. Looking for ways to create the datamodel.
The data being sent to/from the client is JSON. Since database is MongoDb, the data to/from the db is JSON.
I'm new to JS, I could find so many js libraries dedicated to creating encapsulated objects. Is it still required?
What are the possible consequence of just defining models as simple js objects, and use prototype based inheritance where necessary?
Any help is appreciated. Thanks.
What are the possible consequence of just defining models as simple js
objects, and use prototype based inheritance where necessary?
IMO, You will lose maintainability over the time as your application size increases or your team size increases as many developers start working on the same code.
In other words - Without proper encapsulation it is easy to modify objects one doesn't own - easy to meddle with the parts that you don't want to be touched.
If you are writing a library/framework of some sort where the just APIs are exposed to the user and you don't have proper encapsulation one could probably bring everything down by just one modification.
For example:
var myObj = {
mySecretPrivateCrucialFunction: function () {
// all the awesome crucial logic
},
//This is what you want other parts of the code ...
// ... to be interacting with in this object
myPublicMethod: function () {
// some logic
mySecretPrivateCrucialFunction();
// some thing else
}
}
I can do this.
myObj.mySecretPrivateCrucialFunction = function () {
alert('yay..i got you..');
};
But if you do this way - you don't give that chance.
var myObj = (function () {
var mySecretPrivateCrucialFunction = function () {
// all the awesome crucial logic
}
//This is what you want other parts of the code ...
// ... to be interacting with in this object
return {
myPublicMethod: function () {} /*some logic */
mySecretPrivateCrucialFunction(); /*some thing else */
}
})();
In case you want to make all your properties hidden/private and still want to get the JSON representation of the object - you can do something like this -
var myObj = (function () {
// your private properties
var prop1 = 1;
var prop2 = 2;
// your getters
var getProp1 = function () {
return prop1;
};
var getProp2 = function () {
return Prop2;
};
// your setters
var setProp1 = function (newValue) {
prop1 = newValue;
};
var setProp2 = function (newValue) {
prop2 = newValue;
};
// your JSON representation of the object
var toString = function () {
return JSON.stringify({
prop1: prop1,
prop2: prop2
});
};
// Object that gets exposed -
return {
"getProp1": getProp1,
"getProp2": getProp2,
"setProp1": setProp1,
"setProp2": setProp2,
"toString": toString
}
})();
There are two ways to approach this question as I see it:
I'm assuming that your data is being transfered as a JSON string.
"[{\"key\":\"val\"}]" is showing up in your responses, and you are then putting them through JSON.parse to turn them into viable arrays and objects.
So the first way would be to make "class-instances" (no new or inheritance necessary, just a constructor function which encapsulates data and exposes an interface, based on the data-type).
function makeTweet (data) {
var tweet = {
from_user : data.from_user || "anonymous",
/* ... */
},
toString = function () {},
public_interface : {
toString : toString,
/* getters, etc */
};
return public_interface;
}
I know you already know this stuff, but consider a situation where you've got two or three different data-types inside of the same process (like at the end of the line, when you're ready to print to the client), and you have a process which is reading and writing to public fields on every object. If different objects have different properties, things end poorly, or end in a sea of flakey if statements.
The other way to look at it might be an entity/service system
function handleTweets (tweetArr) {
var templateFormat = system.output_format,
string = "";
if (templateFormat === "HTML") {
string = HTMLtemplateTweets(tweetArr);
} else { /* ... */ }
}
function HTMLtemplateTweets (tweetArr) {}
function JSONtemplateTweets (tweetArr) {}
function XMLtemplateTweets (tweetArr) {}
...
With the point being that you would turn the JSON string into an array of data-only objects, and feed them down a line of type-specific library/system functions.
This would be more like a very simplified entity/system approach, rather than an OO (as classically accepted) approach.
Now, your data safety comes from making sure that your objects only ever go down one intended path, and thus transforms will be predictable for every object of that type.
If you want "inheritance" for performance/memory purposes in JS, then this might also be a direction to look.
I'm trying to prototype a custom logger with different levels (debug, info, warn...) each one with different properties like color, name etc.
What I'm trying to do is build dynamically all those levels, getting them from a Hashmap where I store all the properties.
So for example I have my custom logger object with logger.debug('test'), logger.info('text), and so on. You get the idea.
BUT, I'm having problems with this particular code:
var MyLogger = function(opts) {
this.level = opts.level || 0
this.loggers = {}
var self = this
for (l in LEVELS) {
this.addLogger(l, new loggerOutput(LEVELS[l]))
this[l] = function(message) {
self.getLogger(l).output(message)
}
}
}
The problem is with self.getLogger(l), as it always point to my last logger (ERROR). If I replace the variable with a static string, it works: self.getLogger('info')
The workaround is to prototype by hand all loggers, and obviosly that works, but I was expecting to find a better solution:
MyLogger.prototype = {
debug: function(message) {
this.getLogger('debug').output(message)
},
info: function(message) {
this.getLogger('info').output(message)
}
...
}
Thank you in advance.
Use the prototype solution, but assign the functions in a loop by passing the current "level" to a function factory.
for (var L in LEVELS)
MyLogger.prototype[L] = loggerMaker(L)
function loggerMaker(l) {
return function(message) {
this.getLogger(l).output(message)
};
}
Here I used a function to create a new variable scope that references the current L in the loop.
If you're coding only for modern JavaScript environments, I'd use an Array instead of an Object to hold the levels, and then use forEach with an anonymous function.
;['debug','info','warn'].forEach(function(L) {
MyLogger.prototype[L] = function(message) {
this.getLogger(L).output(message);
};
});
I've put these together with the help of others and several resources. I've made a fiddle of everything, and the stripped down code is posted below.
Basically I've learned how to use each of these patterns but I'm curious about the more fundamental differences between these approaches. Downstream code is practically identical with any of these patterns, but is there a reason why one should use one over another, beyond personal preference? Also though I've tried to gather up the most common patterns, please suggest your own if it's better.
Pattern 1 (Object Based):
var mouseDiff = {
"startPoint" : {"x" :0, "y" : 0},
"hypotenuse" : function(a,b) {
// do something
},
"init" : function(){
// do something
}
}
mouseDiff.init();
Pattern 2 (Most traditional as far as I know):
function MouseDiff() {
this.startPoint = {"x" :0, "y" : 0};
}
MouseDiff.prototype.hypotenuse = function(a,b) {
// do something
}
MouseDiff.prototype.init = function() {
// do something
}
var myMouse = new MouseDiff;
myMouse.init();
Pattern 3 (Making use of closure):
var MouseDiff2 = (function() {
var startPoint = {"x" :0, "y" : 0};
var hypotenuse = function(a,b) {
// do something
};
return {
hypotenuse: hypotenuse,
init : function(){
// do something
}
};
}());
MouseDiff2.init();
Pattern 1 is a singleton. If you only need one such object, it's just fine.
Pattern 2 builds new objects, and takes advantage of the prototype object so that when a new MouseDiff object is created, it will not create new copies of the functions (which are themselves data in JavaScript).
Pattern 3 requires more memory in comparison to a regular singleton but it offers static privacy.
I like the following pattern, as it covers various features, though it is really a combination of the constructor (pattern 2) and closure (pattern 3):
var MouseDiff = (function () {
var aStaticVariable = 'Woohoo!';
// And if you really need 100% truly private instance
// variables which are not methods and which can be
// shared between methods (and don't mind the rather
// big hassle they require), see
// http://brettz9.blogspot.com/search?q=relator
// (see also the new plans for a Map/WeakMap in ECMAScript)
function _APrivateStaticMethod () {
alert(aStaticVariable);
}
// An instance method meant to be called on the
// particular object as via ".call(this)" below
function _APrivateInstanceMethod () {
alert(this.startPoint.x);
}
// Begin Constructor
function MouseDiff() {
this.startPoint = {"x" :0, "y" : 0};
}
MouseDiff.prototype.hypotenuse = function(a,b) {
// do something
};
MouseDiff.prototype.init = function() {
// do something
_APrivateStaticMethod(); // alerts 'Woohoo!'
_APrivateInstanceMethod.call(this); // alerts 0 (but if not
// called with this, _APrivateInstanceMethod's internal
// "this" will refer (potentially dangerously) to the
// global object, as in the window in the browser unless
// this class was defined within 'strict' mode in which
// case "this" would be undefined)
};
return MouseDiff;
}());
var myMouse = new MouseDiff;
myMouse.init();
I do not know enough about JavaScript to tell you what if any performance differences exist between these approaches. Here are just two differences between these I noticed. I'm sure there are others.
Pattern 1 creates one object with those properties, including attached methods. Pattern 2 allows us to easily create many objects with the same methods attached, without rewriting them.
Pattern 3 is like a factory. Instead of relying on prototype to automatically attach these methods, the factory just creates them anew and returns the object. The usage of a closure allows us to hide the "member variables" of the object. There is no way to access startPoint or hypotenuse() except through the "public" interface returned.
Whenever I answer these types of theoretical JavaScript questions, I always fear there is some technical detail I am forgetting or overlooking. If so, let me know, and I will fix the answer.
Pattern two is my personally preference because it is the closest to traditional object oriented programming and allows for easy inheritance.
This post by John Resig (the guy behind JQuery) uses that method...
http://ejohn.org/blog/simple-javascript-inheritance/
[edit]
In fact, I don't think methods 1 or 3 have any benefits. 1 is, as someone else said, a singleton and does not allow multiple instances and 3... I don't know where to start with 3.
There is one more possible way to do this.
var MouseDiff = {};
(function(context) {
var privateVarialble = 0;
context.hypotenuse = function() {
//code here
};
context.int = function() {
//code here
}
})(MouseDiff);
Here we simply pass the namespace as an argument to a self-invoking function. The privateVarialble variable is private because it does not get assigned to the context.
We can even set the context to the global object (with a one word change!). Inside brackets (MouseDiff) make it (this). This is a big asset for library vendors – who can wrap their features in a self-invoking function and leave it to the user to decide whether they should be global or not.
http://www.jsoops.net/ is quite good for oop in Js. If provide private, protected, public variable and function, and also Inheritance feature. Example Code:
var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public
pri.className = "I am A ";
this.init = function (var1)// constructor
{
pri.className += var1;
}
pub.getData = function ()
{
return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
+ ", ID=" + pro.getClassId() + ")";
}
pri.getClassName = function () { return pri.className; }
pro.getClassName = function () { return pri.className; }
pro.getClassId = function () { return 1; }
});
var newA = new ClassA("Class");
//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)
//***You can not access constructor, private and protected function
console.log(typeof (newA.init)); // undefined
console.log(typeof (newA.className)); // undefined
console.log(typeof (newA.pro)); // undefined
console.log(typeof (newA.getClassName)); // undefined
This has been answered elsewhere many times before but just to offer up some variety. ds.oop is a nice way to declare classes with constructors in javascript. It supports every possible type of inheritance (Including 1 type that even c# does not support) as well as Interfaces which is nice.
var Color = ds.make.class({
type: 'Color',
constructor: function (r,g,b) {
this.r = r; /* now r,g, and b are available to */
this.g = g; /* other methods in the Color class */
this.b = b;
}
});
var red = new Color(255,0,0); // using the new keyword to instantiate the class