nodejs how to scope parent object to mysql query anonymous callback - javascript

I'm new to node.js and not yet fully into scoping of anonymous functions. I declared a object with several methods. Inside my method I first get a mysql connection from mysql pool and than do a query on the connection. Now I want to call a method of my object. After reading into scoping and binding i came to the following code as result.
I was wondering whether the following is bad practise or good and if there are any better patterns to achieve this?
function myclass() {}
myclass.prototype.dosomthing = function () {}
myclass.prototype.init = function() {
pool.getConnection(function(err,connection)){
this.dosomthing();
connection.query("sql_statement", function(err,rows){
this.dosomething();
}.bind(this));
}.bind(this));
}
Thx, I really appreciate your expertise!

What you have is fine, although it does involve creating unnecessary function objects (bind creates and returns a new function).
As an alternative, just use a variable you close over:
function myclass() {}
myclass.prototype.dosomthing = function () {}
myclass.prototype.init = function() {
var self = this; // Remember `this`
pool.getConnection(function(err,connection)){
self.dosomthing(); // Use it
connection.query("sql_statement", function(err,rows){
self.dosomething(); // Use it
});
});
};
I've used self above, but generally I pick a name based on what the object actually is. So for instance, if myclass were Foo, I'd probably use the name thisFoo or similar.
Side note: The overwhelming convention in JavaScript is that functions meant to be used as constructors are named with an initial uppercase character. So MyClass rather than myclass.

Related

Call another object's method in another object

How does one call another object's method in the current method?
Example:
function OjbectA() {}
ObjectA.prototype.doWork = function () {
alert('do work');
}
var objectA = new ObjectA();
function ObjectB() {}
ObjectB.prototype.method = function() {
// How to call Object A's doWork() method
}
Current attempt:
// Call doWork
ObjectA.doWork();
Error: "Type Error: doWork() function is not defined.
Question:
What is the correct way to call the method of another object WITHIN the method. What about scoping?
Does ObjectA have to instantiated to call it's methods?
What about the apply() or call() method? I am confused how they apply in this situation.
Final remarks
I want to thank everyone's input in advance. I have only recently made the dive into javascript's OOP. This seemingly simple question is something that I have been struggling all day and I came on here as a final resort.
What is the correct way to call the method of another object WITHIN the method. What about scoping?
There is no one "correct" way. Presumably you want to be able to call a method of ObjectA instances (i.e. a method of ObjectA.prototype) but have an instance of ObjectB as this, so:
ObjectB.prototype.method = function() {
// How to call Object A's doWork() method
ObjectA.prototype.doWork.call(this);
}
That will call the method and set the instance of ObjectB as this.
Does ObjectA have to instantiated to call it's methods?
If you mean "does and instance of ObjectA have to instantiated to call its methods" then no, as shown above. You can call the method on the constructor's prototype directly.
What about the apply() or call() method? I am confused how they apply in this situation.
See the answer to the first question. Whether to use call or apply depends on the arguments that need to be passed and whether you intend do to any processing on them first.
Additional answers
Could you explain the mechanics of ObjectA.prototype.doWork.call(this) a little more?
It calls the method and sets its this to the supplied object. The rules for how a value is assigned to this are explained in EMCA–2626 §10.4.3.
Would ObjectA.prototype.doWork(this) work just the same way?
No. That calls the function, sets its this to ObjectA.prototype and supplies the value of this from the calling execution context as the first parameter. e.g. if it's global code in a browser, effectively:
ObjectA.prototype.doWork(window);
There is a typo, not ObjectA.doWork(); use objectA.doWork();
There really seems to be some confusion with JavaScript's general OOP model.
Every function has an underlying prototype, which is just an object. You may or may not add anything to it, but if you do, you probably plan to use that function as a constructor. That's what you see happening here:
function ObjectA() {}
ObjectA.prototype.doWork = function () {
alert('do work');
}
var objectA = new ObjectA();
objectA.doWork();
However, in some instances, it might be more appealing to just create a function with some methods directly attached to it, rather than creating instances of it. Generally, these would be static methods as in other languages, or perhaps your function is really just a singleton object. In this case, you would omit the prototype, and just attach directly, like so:
function ObjectA() {}
ObjectA.doWork = function () {
alert('do work');
}
ObjectA.doWork()
Going back to the first example, if you define your function and add methods to its prototype, occasionally you may wish to actually call a function that you have defined in a different function's prototype. call and apply can be used to call any function with the value of this changing to the object which you pass into apply or call.
Remember that you are attaching methods to the prototype, so it may look a little funky, but here's an example:
function ObjectA() {}
ObjectA.prototype.doWork = function () {
console.log(this)
}
var objectA = new ObjectA();
function ObjectB() {}
ObjectB.prototype.method = function() {
ObjectA.prototype.doWork.call(this);
}
var objectB = new ObjectB();
objectB.method()
// -> objectB will be logged to your console, bc
// it became the value of this in ObjectA's doWork method.
It's possible to call it from the prototype directly.
Using apply changes the value of this in the execution of the function to the supplied value, so its essentially forwarding this to be itself in the call.
You could also use call, the difference is just in how it takes its arguments, apply takes an array whereas call takes an argument list.
ObjectB.prototype.method = function() {
ObjectA.prototype.doWork.apply(this);
}
However of course an ObjectB does not necessarily have same properties as an ObjectA so make sure you write the method as generic as possible. In order words use a documented concept rather than internal implementation details.
Example again lies with how Array, it's generically applicable methods are documented as such and states what is required for it to work.
In the case you just want to expose a 'utility function', just put it on the object itself. e.g
ObjectA.doWork = function(obj) {
};
After all I found your typo:
function OjbectA() {}
Should be function ObjectA() {}
That's why you were facing error.
function ObjectA() {}
ObjectA.prototype.doWork = function () {
alert('do work');
}
var objectA = new ObjectA();
function ObjectB() {}
ObjectB.prototype.method = function() {
objectA.doWork()
}

Initiate a scoped function from a string in javascript

Lets define a dog:
function Dog() {}
Now lets define a self executing function that passes the Dog as a parameter:
(function(dogClassName) {
var someServerSideLogicResolvesClassName = "dogClassName";
//Iniate class name from the server side string
})(Dog);​
After some googleing I found that I should use
new window["dogClassName"]();
or
new this["dogClassName"]();
But since it's a scoped variable it doesn't exist in the global name space (no window) and this is undefined; I have no idea how to achieve this without using some sort of evaling.
Right, assuming that you're trying to access a constructor that isn't set globally, then the answer to your question is, quite simply: you can't do this. The scopes of closures are managed differently by the various engines. V8 might even GC the constructor if the returned function doesn't reference it explicitly... There is no magic way to get a full outer scope as an object
The only solution would be to create a namespace-object:
(function()
{
var constructors = {Constructor1: function(){},
Constructor2: function(){}};
return function()
{
var className =getClassNameViaAjax();
if (constructors.hasOwnProperty(className))
{
return new constructors[className]();
}
if (window[className] instanceof Function)
{//fallback
return new window[className]()
}
throw className + ' Does not exist in closure, nor in global scope';
};
}());
Have a look at this question, it seems to me to be related, or even a duplicate.
Hesitant update, but for completeness
There is one way you can use a variable's value as reference in the scope chain, but it does require the most Evil of Evil functions: eval('new '+ className + '()'), as you can see in the specification, eval will preserve the this bindings, and reinitialize the scope chains. Except when you're using 'strict mode';Since you're getting the constructor name from an ajax response, and eval is an easy thing to exploit, don't do this! This is a sort of an "in theory, you could..." thing.

Why cant I declare a constructor instantiate an object and then access the prototype?

The below doesnt work and im struggling to work out why....
function CommentHandler() {
var Text;
}
var myCommentHandler = new CommentHandler();
myCommentHandler.prototype.SayHello = function () {
document.write('Hello World');
}
I get the error : 'myCommentHandler.prototype is undefined'
I just cant see why? I have declared a variable called myCommentHandler and copied in the object CommentHandler then Im trying to access the protoype of it and assign a function but I cant...Anyone know why?
The prototype belongs to the class, not the instance:
CommentHandler.prototype.MyFunction = ...
However you can also access the prototype via the instance's constructor property:
myObj.constructor.prototype.MyFunction = ...
This will of course add that function to every instance of your CommentHandler.
If instead you only wanted to add that function to that one instance, you'd do:
myObj.MyFunction = ...
Note that in none of these variants would it be possible for MyFunction to access your private variable Text.
This is the compromise forced by the prototype inheritance model - variables and methods must be public (e.g. this.Text) if they're to be accessed from outside, and in this case functions declared in the prototype are effectively "outside".
The alternative (using closure-scoped variables and methods) seems more natural to OO programmers, but makes inheritance much harder.
I think what you actually want here is this:
CommentHandler.prototype.SayHello = function () {
document.write('Hello World');
};
You have to use
CommentHandler.prototype.SayHello = function(){....}
You can find more about the prototype object in the following references
http://www.javascriptkit.com/javatutors/proto.shtmlhttps://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/prototypehttp://msdn.microsoft.com/en-us/magazine/cc163419.aspx
You need to prototype the class function rather than the instance. Also if you want the Text variable to be accessible outside the constructor, in the other method functions, then you need to add the this keyword.
function CommentHandler() {
this.Text = 'Hello World';
}
CommentHandler.prototype.SayHello = function () {
document.write(this.Text);
}
var myCommentHandler = new CommentHandler();
myCommentHandler.SayHello();
As a side point you could create the SayHello function inside the constructor, but this would add increased overhead to the creation of each instance of CommentHandler. Thus the prototyping method that you are using is a better option.
myCommentHandler does not have a prototype, because it is an instance. CommentHandler does have a prototype that can be modified. I am guessing you want to edit the object after initializing, and can do so like this:
myCommentHandler.SayHello = function() {
document.write('Hello World');
}
Here is a good explanation of prototypes and object oriented programming in javascript with many examples: http://mckoss.com/jscript/object.htm

Method and variable scoping of private and instance variables in JavaScript

I have tried to figure this out or search for it on google, i can only find how to create objects, not exactly how functions work. If someone could explain to me how encapsulation works.
function myObject() {
this.variable1 = "tst";
this.function1 = function() {
//Now this function works. A 'this' function to a private function is ok
_PrivateFunction1();
//Here is error one, I cannot seem to call methods within the object
//from.
this.function2();
}
this.function2 = function() {
alert("look! function2!");
}
function _PrivateFunction1() {
//This does work though. I am confused.
_PrivateFunction2();
}
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(this.variable1);
}
}
I think I can explain this better if we go in reverse order. First, we define some functions:
function _PrivateFunction1() {
//This does work though. I am confused.
_PrivateFunction2();
}
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(this.variable1);
}
This is pretty normal stuff. The only thing that's weird is that they appear inside another function, but that's perfectly fine. JavaScript has function scope, which means that all variables defined inside a function are defined in a new scope. They do not trample on the global namespace. And functions are first-class objects in JavaScript, which means they can be used just like other data types. They can be nested, passed to functions, returned from functions, etc.
Then we run into some trouble:
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(this.variable1);
}
}
Functions in JavaScript are always executed in some context which is referred to by the this keyword. When you call a function directly (i.e. like this: functionName()) the context in which that function executes is the global window object. So, inside _PrivateFunction2, this.variable1 is equivalent to window.variable1 which is probably not what you meant.
You probably wanted to refer to the current instance of myobject which is what this refers to outside of _PrivateFunction2. You can preserve access to this in an inner scope by storing a reference to it in another variable:
var _this = this;
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(_this.variable1);
}
There's something subtle here you should notice. _PrivateFunction2 has access to the variables defined in its lexical scope, which is why it can access _this. This will be important later.
Next up:
function _PrivateFunction1() {
//This does work though. I am confused.
_PrivateFunction2();
}
This should be the most normal-looking section to you, I would think. There's nothing strange going on here. Just one regular function calling another one. Don't be confused by the fact that these are nested inside myObject. That changes the scope they're in, but not much else.
Next we define some instance variables and methods:
this.variable1 = "tst";
this.function1 = function() {
//Now this function works. A 'this' function to a private function is ok
_PrivateFunction1();
//Here is error one, I cannot seem to call methods within the object
//from.
this.function2();
}
this.function2 = function() {
alert("look! function2!");
}
Here this really does refer to myObject, assuming -- and it's an important assumption -- that myObject was called with the new operator, like this:
var obj = new myObject();
If it had been called like this:
var obj = myObject();
Then this would refer to the window object, just like it did for the functions we saw earlier. The key takeaway is that the value of this is not fixed. It's determined by the way in which the function is called. There are even ways to set it to an arbitrary object explicitly.
The value of this inside this.function1 will also be the current instance of myObject, because it will most likely be used like this:
var obj = new myObject();
obj.function1();
Writing object.method() sets this to object inside method.
So how is this.function1 able to call _PrivateFunction1()? Just as we saw earlier when saving the value of this for use inside a nested function, _PrivateFunction1() is just another object defined in this.function1's lexical scope, so it is available for its use, just as _this was earlier.
And it's because of closure that these private variables are still alive long after myObject has returned.
Footnote: Because failing to use new when instantiating objects breaks things so spectacularly without warning, it's considered good practice to capitalize the names of functions you intend to be used as a constructor. So myObject should really be MyObject.
You have to save a copy of the actual object like here note the var that = this
Tested in chrome and FF
for encapsulation I would prefer module pattern like
var someMethod = function(){
var i,
length,
// public method
public = function(num1, num2){
return num1+num2;
},
//private method
_private = function(){};
//exposing the public method
return{
public:public
}
};
var callPublic = someMethod();
callPublic.public(20, 30);// call the public method and return 50
now , if you try to call that private method like
callPublic._private();//it will return not a function since its not been exposed
There are lot of other pattern to encapsulate your methods but module pattern is most common. Hope ot will help you how to encapsulate data in javascript.

Javascript - get class owner of a function(method)

there is a way to know what class own a function?
Example:
function globalFunc(){
//alert MyObject
}
function MyObject(){
}
MyObject.prototype.test=function(){
globalFunc();
}
var o=new MyObject();
o.test(); //alert MyObject
Now im using this workaround:
function globalFunc(){
alert(globalFunc.caller.__class__);
}
function MyObject(){
}
MyObject.prototype.test=function(){
globalFunc();
}
MyObject.prototype.test.__class__=MyObject;
var o=new MyObject();
o.test(); //alert MyObject
But there is a big problem, look this:
function globalFunc(){
alert(globalFunc.caller.__class__);
}
function MyObject(){
}
MyObject.prototype.test=function(){
var temp=function(){
globalFunc();
}
temp();
/* to simulate a simple closure, this may be for example:
element.addEventListener("click",temp,false);
*/
}
MyObject.prototype.test.__class__=MyObject;
var o=new MyObject();
o.test(); //alert undefined
So, there is a clear way to obtain this?
I know where is the problem(class property is a property of only test and not temp), but i can't add class to temp too.
Thanks.
Thanks for reply, some clarification.
Im trying to do a personal framwork OO oriented with private members.
So:
globalFunc is a special function, im using it to get "private" property and i can't call it with call method or passing some arguments, the only arguments im pass is "this":
Example, $() is global
Class({
public:{
MyClass:function(){
},
setName:function(name) {
$(this).name=name; //set the private var name
},
getName:function(){
return $(this).name;
}
},
private:{
name:"UNKNOWN"
}
})
var o=new MyClass();
o.getName(); // UNKNOWN
o.setName("TEST!!!");
o.getName(); // TEST!!!
o.name; //undefined
$(o).name; //undefined
To works with inheritance, $(), i need to know what class call it and the object of the class.
All works good, but if i need to access a private members in a clousure i must add
__class__
property to clouser!! And i not want this!
Thanks again and sorry for my bad english, im not native speaker.
In javascript there are no Classes. Instead several objects can "own" the same function. For example:
function myFun(){
alert(this.name);
}
function Obj1(){
this.name = "obj1";
}
Obj1.prototype.fun = myFun;
function Obj2(){
this.name = "obj2";
}
Obj2.prototype.fun = myFun;
var obj1 = new Obj1();
var obj2 = new Obj2();
obj1.fun();
obj2.fun();
You scenario is not entirely clear but here are some options:-
function globalFunc()
{
alert(this.__class__);
//Note globalFunc now has access to much more.
}
function MyObject(){ }
MyObject.prototype.test=function(){
globalFunc.call(this);
}
MyObject.prototype.__class__=MyObject;
To add a closure for event handling
MyObject.prototype.test = function(){
var self = this;
var elem = //get some element;
//Not cross-browser but for illustration
elem.addEventListener('click', fnEvent);
function fnEvent() { globalFunc.call(self); }
elem = null
}
I don't understand well what you are trying to do, but here's an idea that could inspire you something.
The "constructor" property helped me well when I was trying to use JS as a OO language.
o.constructor will give you the myObject function reference.
But in my opinion, you should give functional programming a try instead of OO to get the most from Javascript
temp is the caller but it does not have the property __class__. You only defined that for test.
caller is non-standardised and really brittle; best avoided. Much better to pass the value explicitly:
MyObject.prototype.test= function() {
element.addEventListener('click', function() {
globalFunc(MyObject);
});
};
or:
MyObject.prototype.test= function() {
var myclass= arguments.callee.__class__;
element.addEventListener('click', function() {
globalFunc(myclass);
});
};
Functions are not "owned" in JavaScript. Functions are first class objects in JavaScript, which means they can be passed around like any other variable and assigned as properties of many objects.
this inside a function body will give you a reference to the object on which the function was called, if called as a method (e.g. myObj.myMethod()) or via the Function prototype's call() or apply() methods (e.g. myFunc.call(myObj)). Inside a function called on its own (e.g. myFunc()), this will usually be the global object (the same as window in most browsers).
Short answer, there really is no way to do what you are trying to do. Javascript just doesn't work like that.
Long answer...
Almost every programmer I've met who has come to JavaScript from a language that uses a classical object model has tried to do what you are doing: emulate the classical OOP style they are used to with Javascript.
There is no shame here, I did this, even the famous Douglas Crockford experimented with this, and then later gave it up. I did too. I still think it was a neccessary thing for me to try this stuff in order to really learn the langauage
Do not be fooled by the curly braces, and familiar looking operators. At it's core it has very little in common with Java! JavaScript is a functional langauge: functions are objects in their own right.
Bluntly: There is no way to do what you are trying to do - have objects with private properties you can access through this
Saying that is easy :) Understanding how to apply that is more difficult
There are no classes, there are only objects.
Objects only have properties.
Properties of objects may have values.
Those values may be functions.
this is set when the function gets called, it could be anything
Closure is the only way to achieve true privacy in JavaScript. Everything else either leaks into some enclosing scope, relies on obfuscated property names, or can be circumvented in some way by the caller, or leaks memory even after your objects are no longer referenced (as there are no destructor function to do your clean-up in).
What you are doing is still a good thing to try and do, by attempting it you will become a better JavaScript programmer by figuring out:
why you can't do some of it
more importantly why you probably shouldn't

Categories