Function scope in JavaScript. Different objects same result - javascript

My question is based on the following scenario.
var test = (function(){
var SlideManager = !function(){
this.Sequencer = {
getSequence : function()...
}
return this;
}()
var LayerManager = !function(){
this.Sequencer = {
getSequence : function()...
}
}()
var module = {};
module.foo = function(){}
return module;
})()
As an explanation, the test object has two helper objects in its scope: SlideManager & LayerManager. These two handle different actions for the entities slide && layer. Each entity has its own fixed position in the DOM, position which should be retrieved through the Sequencer helper object.
Please note that every Manager should have its own Sequencer and I would expect that to be true in the provided example.
However it seems that there is a problem with my understanding of js scopes because both Managers have the same Sequencer (The one from Layer Manager).
Should I expect something like this or am I doing something wrong somewhere else in the code.
Thank you!

To expound upon what Scott Hunter said...
Just auto executing the functions (function() {})() Does not give them a new scope. For that you are wanting the "new" keyword.
So:
var SlideManager = function(){
this.Sequencer = {
getSequence : function()...
}
return this;
};
var LayerManager = function(){
this.Sequencer = {
getSequence : function()...
}
};
var slideManagerInstance = new SlideManage();
var layerManagerInstance = new LayerManager();
Might be more what you are looking for... also why are you "!" banging the auto executed functions return before assigning... that will give you a true/false boolean?

this in both Managers isn't local to that function, and thus is the SAME in both, which is why they have the same Sqeuencer.

Related

Losing context in JS function call chain

I have got some JS "objects" I'm using for some complexe stuff. So the following code is reduced to the needed minimal informations:
function AttributeWrapper(model) {
var self = this;
var attributeModel = model;
self.labelPrimitive = null;
self.mandatorySignPrimitive = null;
self.documentationPrimitive = null;
self.valuePrimitive = null;
self.isHidden = function() {
return false;
}
}
function Primitive(model, wrapper) {
var self = this;
var groupingObject = wrapper;
self.model = model;
self.layoutCell = null;
self.render = function() {
if (self.isHidden()) {
return;
}
self.layoutCell.getDomElement().innerHTML = self.model.id || "TODO";
}
self.isHidden = function() {
return groupingObject.isHidden();
}
}
This objects are used mainly like this:
function AnOtherObject {
var self = this;
self.anyFunction = function() {
var wrapper = new AttributeWrapper(model);
var primitive = new Primitive(anOtherKindOfModel, wrapper);
var isHidden = primitive.isHidden();
}
}
For any reason the first call works fine. So the function in the Primitive "class" is called and the scope is correct (variables are set as expected). Also the call by the Primitive class of its contained object (instance of AttributeWrapper) works, but there the context is messed up. I would expect that I can access the instance variables like attributeModel in the "isHidden" function but they do not exist anymore. Also "self" is not the instance but something else (looking like the global "document" or "window" instance), but "this" revers to the instance...
Is there anything i did wrong at the declaration of the objects? I do not understand why the call of the first objects works but the sub-object is wired...
Problem seems to be solved...
I'm using visual studio for debugging. The "return false" of the "isHidden" function in AttributeWrapper was written to place a breakpoint and continue writting the code for this function (to see the objects and their fields in the debugger). When the breakpoint was hitted I had the descript problem.
Today I had a look on it with a colleague who had the idea that maybe just the debugger is confused somehow and do not show the correct state.
So i finished the code and started debugging again. Suddenly the state was correct when the breakpoint gets hit.
So it seems the problem realy was a confused debugger and everthing was working correctly. By using something from the context in the function this confusion seems to be solved...
Lesson learned: visual studio maybe isnt the best choice to debug javascript =)

JavaScript getter and setter

This is such a fundamental question, that I'm sure it's a duplicate, so I apologize in advance, but is this how I write an object such that I use by saying:
myApplication.myFirstMethod(x);
x = myApplication.myFirstMethod();
Here's the code:
myApplication = {};
(function() {
myApplication.myFirstMethod = function() {
var local = {};
if (arguments.length) {
local.result = arguments[0];
}
return local.result;
}
myApplication.mySecondMethod = function() {
var local = {};
if (arguments.length) {
local.result = arguments[0];
}
return local.result;
}
})();
jsFiddle Demo
A more object oriented approach would be to use instantiation and prototype.
Setup
var Application = function(){
this.local = {};
};
Application.prototype.Value = function(){
if (arguments.length) {
this.local.result = arguments[0];
}else{
return this.local.result;
}
};
Used
var app = new Application();
app.Value(6);
alert(app.Value());//6
From a jQuery point of view, they will first screen to see if there are arguments, this code is direct from their source for the val function:
val: function( value ) {
if ( !arguments.length ) {
var elem = this[0];
...
It then goes on to use the element's native API and some other metrics to get the value for the element (In general, the only type of elements which will return a value from val are going to be elements such as input, select, etc. - form elements basically).
At the end of the if block it attempts to return various results based on if it found a value attached to the element (or set of elements). This guarantees that the clause of "setting" never executes when a "get" is encountered. If the case is that "set" is being used it goes through a slightly complex set of code to properly set a value to the element.
The reason that the code shows val: function() is because it is part of an object which is being used to "extend" the jQuery prototype using jQuery's extend functionality.
This is the exact code in a jsfiddle of jQuery's val function
There are many patterns for creating objects like this and everyone has their favorites. Addy Osmani does an excellent job of summarizing the most popular patterns in his Javascript Design Patterns "book". Specifically, this section:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#designpatternsjavascript
I reread this semi-annualy just to make sure I'm keeping all the patterns in my quiver.

Understanding Classes and Inheritance in Javascript - New Pattern

I'm designing an OOP inheritance pattern for many applications I'm building. Javascript has many ways of doing this, but I stumbled on a pattern I really like. But now I'm struggling with the need for a separation of classes and instances.
I have a base object called Root. And it has a main method called inherit. To create a new object you use
var Person = Root.inherit({
name : "",
height : 0,
walk : function() {},
talk : function() {}
});
Then to create an "instance" you would
var sally = Person.inherit({
name : "sally",
height : "5'6"
});
sally can .talk() and she can walk() and she has a .name and a .height
You can make more people the same way.
If you want a constructor you use
var Person = Root.inherit({
_construct : function() {
// do things when this object is inherited from
},
name : "",
height : 0,
walk : function() {},
talk : function() {}
});
It also has the ability to have init, when the object is first defined in code (singletons use this)
var Person = Root.inherit({
_init : function() {
// called at runtime, NOT called if an object is inherited from me
},
name : "",
height : 0,
walk : function() {},
talk : function() {}
});
So as you can see, everything uses .inhert(). There are no classes and no instances really. Everything is an instance of something. The only real problem I found so far is that there is no concept of "type", but you can always just check for a method if you need to. Also you can't protect a 'class', as a 'class' can be changed during execution if the developer accidentally changed it, or meant to change it.
So my question is: Is there a need in javascript to have an explicitly and controlled separation of class structure and instances of the class? Are there any issues with treating every object as an instance?
No there's no need since Javascript is a Prototypal based language, meaning that classes are not involved. You are just creating clones of the objects.
http://en.wikipedia.org/wiki/Prototype-based_programming
As far as the concept of type, the type is object.
A good read for more info about this would be Javascript Patterns by Stoyan Stefanov he has several different creational patterns that address your concerns, including examples that implement Design Patterns from the gang of four's design patterns.
http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752
So my question is: Is there a need in javascript to have an explicitly and controlled separation of class structure and instances of the class? Are there any issues with treating every object as an instance?
Not really, if you're happy with it, it's fine.
The more normal form of JavaScript inheritance does much the same thing. You'll frequently see structures like this (severely cut down for brevity):
function Base() {
}
Base.prototype.foo = function() {
};
function Derived() {
}
Derived.prototype = new Base();
...and of course, new Base() is also how you create instances of Base. So your system is quite similar.
Again, the above is a sketch, not a full example. For one thing, usually you'd see construction and initialization separated out, so you don't literally see Derived.prototype = new Base() so much as something that creates an object with Base's prototype but without actually calling Base (which Derived would do later), but you get the idea. Granted that statement somewhat weakens the similarity with your system, but I don't think it breaks it at all.
At the end of the day, it's all about objects (instances), which are either used directly (your sally) or indirectly by providing features to other objects (Person, Root) by cloning or by setting them up as the prototype of the other object.
Javascript's inheritance is prototypical which means everything object is an instance. You actually have to do extra work to get the classical inheritance.
This is how I work in javascript
// this is class
function person(){
// data is member variable
this.name = null;
this.id = null;
//member functions
this.set_name = _set_name;
this.get_name = _get_name;
this.set_id = _set_id;
this.get_id = _get_id;
function _set_name(name){
this.name = name;
}
function _get_name(name){
return this.name;
}
function _set_id(id){
this.id = id;
}
function _get_id(id){
return this.id;
}
}
// this is instance
var yogs = new person();
yogs.set_id(13);
yogs.set_name("yogs");
hope it may help
Start with some basic object...
// javascript prototypes - callback example - javascript objects
function myDummyObject () {
that = this;
} // end function myDummyObject ()
// begin dummy object's prototype
myDummyObject.prototype = {
that : this,
// add a simple command to our dummy object and load it with a callback entry
say : function () {
var that = this;
console.log('speaking:');
that.cb.run("doSay");
}
} // end myDummyObject proto
extend with a sub prototype..
// here we addon the callback handler... universally self sufficient object
var cb = {
that : this, // come to papa ( a link to parent object [ myDummyObject ] )
jCallback : new Array(new Array()), // initialize a javascript 2d array
jCallbackID : -1, // stores the last callback id
add: function(targetFnc, newFunc) {
var that = this;
var whichID = that.jCallbackID++;
// target, addon, active
that.jCallback[that.jCallback.length] = { 'targetFunc' : targetFnc, 'newFunc' : newFunc, 'active' : true, 'id': whichID };
return whichID; // if we want to delete this later...
}, // end add
run: function(targetFnc) {
var that = this;
for(i=0;i <= that.jCallback.length - 1;i++) // go through callback list
if( that.jCallback[i]['targetFunc'] == targetFnc && that.jCallback[i]['active'] == true )
that.jCallback[i]['newFunc'](); // run callback.
}, // end run
remove: function (whichID) {
var that = this;
console.log('removing:' + whichID);
for(i=0;i <= that.jCallback.length - 1;i++) // go through callback list
if( that.jCallback[i]['id'] == whichID )
that.jCallback[i]['newFunc'](); // run callback.
} // end remove
}
// add the object to the dummy object...
myDummyObject.prototype.cb = cb;
Example:
var testing = new myDummyObject();
testing.cb.add('doSay', function () { console.log('test: 213123123'); } );
// test remove...
var testid = testing.cb.add('doSay', function () { console.log('test: 12sad31'); } );
testing.cb.remove(testid);
testing.cb.add('doSay', function () { console.log('test: asdascccc'); } );
testing.cb.add('doSay', function () { console.log('test: qweqwe'); } );
testing.cb.add('doSay', function () { console.log('test: d121d21'); } );
testing.cb.add('doSay', function () { console.log('test: wwww'); } );
testing.say();
This always seemed the easiest for me to understand... Just create a new instance of the inherited class and then loop through its variables and methods and add them to the main one.
var myPerson = new Person()
var myPerson.firstName = 'john';
var myPerson.lastName = 'smith';
var myPerson.jobTitle = 'Programmer';
var Person = function(){
//Use this to inherit classes
this._extendedClass = new Person_Job();
for(var i in this._extendedClass){
this[i] = this._extendedClass[i];
}
delete this._extendedClass;
this.firstName = '';
this.lastName = '';
}
var Person_Job = function() {
this.jobTitle = '';
}

Structuring a NodeJS module - variables and methods

I want to create modules to structure my NodeJS application, but I'm a little lost, and I haven't found anything (with hours of searching) that is completely definitive on the subject.
Say I'd like to create a "user" module, from which I can create new users in my code using something like:
var newUser = new User();
Ideally, I'd require my module at the top of my code using something like:
var User = require('../lib/user');
This works great. The question is, how should I structure the user module? Is the following the best way?
module.exports = function User() {
var authorized = false;
var username = undefined;
var password = undefined;
var statistics = undefined;
this.authorized = function() {
return authorized;
}
this.username = function() {
return username;
}
this.statistics = function() {
return statistics;
}
}
I'm writing getters and setters for my various module variables, allowing me to hide things I don't want to accidentally access from other code. However, I have done it this way before:
function User() {
this.authStatus = false;
this.email;
this.displayName;
this.inSession;
}
User.prototype.isAuthenticated = function() {
return(this.authStatus && this.email && this.displayName)
}
User.prototype.isInSession = function() {
return(this.inSession && this.isAuthenticated());
}
exports.User = User;
This works too, with one caveat; I haven't found a way to access the user properties from within closures. If my understanding is correct, with the second implementation, I can't. This means if I need to hand a function off to a db library as a callback to edit the user's properties, I can't. That'd look something like:
User.prototype.login = function() {
db.doDbStuff('get user data query', function(_error, _result) {
this.username = _result[0].name; //this code will not work
});
}
The code doesn't work, to my understanding, because the "this" keyword is within the scope of the closure, not the User. Even if the code were to be placed within the User function:
function User() {
this.login = function() { //you know
It wouldn't work.
I guess my question is, what's the best solution to this problem? Is it the method I presented in the first code block? That seems rather cumbersome and messy and prone to variable collision. I'm scared.
Thanks in advance!
I typically go with the second approach, attaching functions to the prototypes.
The issue you're having with variables "not being available in closures" has nothing to do with prototypes. You'd have that same issue either way you structure it.
It's to do with javascript's oft-confusing dynamic this:
http://robotlolita.me/2011/10/09/understanding-javascript-oop.html#sec-2-1
Basically, you need to do something like:
User.prototype.login = function() {
var self = this // bind this to self so you have a reference to what `this` was
db.doDbStuff('get user data query', function(_error, _result) {
self.username = _result[0].name; // self refers to the original `this`, so this works.
});
}
You also have the option of using function.bind: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
Within the bound function, the value of this will be whatever value you provided to .bind(value):
User.prototype.login = function() {
db.doDbStuff('get user data query', (function(_error, _result) {
this.username = _result[0].name; // bind fixes the original `this`, so this also works.
}).bind(this));
}
Whether you use function.bind or self = this is somewhat of a personal taste question, but we were doing some benchmarks in the freenode#nodejs the other day and discovered bind() is 20 something times slower than var self = this.
As to your original question about how to structure modules, there are so many examples to learn from on github. Simply find your favourite module and inspect how they structure it. I notice that many people seem to prefer factories over exposing constructors directly (e.g. require('module').create() ). Your call.
As a different approach, I am a fan of the following pattern.
module.exports = function User(data) {
//this properly private stuff.
var privateVar;
var username = data.username;
var pass = data.pass; //etc
function privateFunc() {
}
return {
login: function(cb) {
db.doStuff(username, pass, cb);
}
};
};
User.prototype.login = function() {
var _this = this;
db.doDbStuff('get user data query', function(_error, _result) {
_this.username = _result[0].name; //this code will now work
});
}
The 'this' you used was outside its scope, it was the callback 'this'.

Javascript apply — Inheriting classes

The code below is adapted from this answer
function MessageClass() {
var self = this;
this.clickHander = function(e) { self.someoneClickedMe = true; };
var _private = 0;
this.getPrivate = function() { return _private; };
this.setPrivate = function(val) { _private = val; };
}
ErrorMessageClass.prototype = new MessageClass();
function ErrorMessageClass() {
MessageClass.apply(this, arguments);
}
var errorA = new ErrorMessageClass();
var errorB = new ErrorMessageClass();
errorA.setPrivate('A');
errorB.setPrivate('B');
console.log(errorA.getPrivate());
console.log(errorB.getPrivate());
The original post did not have the MessageClass.apply(this, arguments); since the purpose was to show how inheritance can go wrong in Javascript.
My question is, is saying: ErrorMessageClass.prototype = new MessageClass(); before the ErrorMessageClass constructor has even been declared bad practice? My understanding is that calling undeclared identifiers like that causes a silent declaration to occur, with the result being placed on the global window object, which I understand is bad.
Is this form:
function ErrorMessageClass() {
MessageClass.apply(this, arguments);
}
ErrorMessageClass.prototype = new MessageClass();
considered to be better practice? This link shows the code written as it was originally above, which is why I even tried it. Does this blogger know something I don't (quite likely)?
EDIT
Lots of great info in the answers below, but I did want to highlight this link which really explains things perfectly
Usually, to avoid this confusion, you would just attach the prototype after, but as Adam Rackis pointed out, function declarations are hoisted, like var statements.
However, you should not instantiate the base object as the prototype. If your base object takes arguments, what are you supposed to use? Use an empty "surrogate" constructor
// Used to setup inheritance
function surrogate () {};
function MessageClass() {
var self = this;
this.clickHander = function(e) { self.someoneClickedMe = true; };
var _private = 0;
this.getPrivate = function() { return _private; };
this.setPrivate = function(val) { _private = val; };
}
// The key steps to creating clean inheritance
surrogate.prototype = MessageClass;
// Sets up inheritance without instantiating a base class object
ErrorMessageClass.prototype = new surrogate();
// Fix the constructor property
ErrorMessageClass.prototype.constructor = ErrorMessageClass
function ErrorMessageClass() {
MessageClass.apply(this, arguments);
}
There's much more to be said. http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html
It works because function declarations are evaluated first. If you tried to move these classes under an object literal "namespace" the first version would fail.
I personally find the second method to be much easier to read - also, don't forget to set the sub-class' prototype.constructor property back to itself. Personally, I use an inherits() method on the Function prototype which wraps up essentially the type of code you're using here.

Categories

Resources