javascript classes scope and anonymous functions - javascript

I have a javascript class declared as shown below.. My problem is the aonymous function does not see the scope of the class. I can not reference the bb_obj from within the ajax call load callback..
Is there a way to do this?
Thanks in advance..
dojo.declare("sop.quote", null,
{
bb_obj : new Object,
stage1 : function()
{
dojo.xhrPost(
{
url : 'go/module_service/transport.php',
content : this.bb_obj,
handleAs : 'xml',
load : function(xml)
{
var status = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue;
this.bb_obj.message = message;
},
error : function()
{
}
}
}
}

this inside a XHR callback function refers to the XHR object. The only way to refer to bb_obj is by directly referring to the created object, in the same scope as the function. Because objects are passed by reference, the code below works as intended.
Note to avoid confusion, I've declared the object using var bb_obj_obj={}. The bb_obj property refers to bb_obj_obj:
bb_obj_obj.message is changed
bb_obj points to bb_obj_obj, hence bb_obj.message refers to the same variable
Code:
var bb_obj_obj = {}; //new Object
dojo.declare("sop.quote", null,
{
bb_obj : bb_obj_obj,
stage1 : function()
{
dojo.xhrPost(
{
url : 'go/module_service/transport.php',
content : this.bb_obj,
handleAs : 'xml',
load : function(xml)
{
var status = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue;
bb_obj_obj.message = message; //Without `this`
},
error : function()
{
}
}
}
}
An alternative method consists of saving this in a variable, eg. $this:
...
stage1 : function()
{
var $this = this;
dojo.xhrPost({
...
load : function(xml){
var status = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue;
$this.bb_obj.message = message; //Using `$this` instead of `this`
},
...

The typical Javascript practice, in this case, is to wrap the whole thing in an an unnamed function. All local variables of this function will be accessible to every object/function declared therein. By immediately calling this unnamed function you make sure the code inside the function gets executed.
(function() {
var bb_obj = {}
dojo.declare("sop.quote", null, {
stage1 : function()
{
dojo.xhrPost(
{
url : 'go/module_service/transport.php',
content : this.bb_obj,
handleAs : 'xml',
load : function(xml)
{
var status = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue;
bb_obj.message = message;
},
error : function()
{
}
}
}
})()

Related

JavaScript Object storage and usage via sessionStorage

var obj = {
conn : null,
first : function(thisIdentity) {
"use strict";
var myObj = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
myObj.conn = new Connection(data.user_id, "127.0.0.1:80");
sessionStorage.setItem('connection', JSON.stringify(myObj.conn));
}
});
},
second : function(thisIdentity) {
"use strict";
var myObj = this;
var conntn = sessionStorage.getItem('connection');
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
var parsedConnection = JSON.parse(conntn);
parsedConnection.sendMsg(data.id, data.nid);
}
});
}
};
var Connection = (function() {
function Connection(uid, url) {
this.uid = uid;
this.open = false;
this.socket = new WebSocket("ws://"+url);
this.setupConnectionEvents();
},
sendMsg : function(id, nid) {
alert("Working");
},
// other functions
})();
Now basically an object is assigned to conn variable in AJAX callback function of first function and I am storing the object via sessionStorage and retrieving the object in the second function and using it in the AJAX callback but when I call the method via parsedConnection.sendMsg(data.id, data.nid); it is throwing an error that
TypeError: parsedConnection.sendMsg is not a function
I did use console.log(parsedConnection); and it shows that object is there with proper values. I just want to know how to retrieve the object and call the method on it in AJAX callback function of second. Thanks!

Assign and use javascript object property via AJAX

So I have this Javascript object :
var obj = {
conn : null,
first : function(thisIdentity) {
"use strict";
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
this.conn = new Connection(data.user_id, "127.0.0.1:80");
}
});
},
second : function(thisIdentity) {
"use strict";
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
// using this.conn now results in UNDEFINED
}
});
}
};
Now basically value is assigned to conn variable in AJAX call of first function but when I try to use the same value in second function then it states this.conn is undefined. I just want to know how to assign value to the object's property and keep it preserved for future use? Thanks!
In the ajax success callback the this refers to a different scope than the original object.
Change you code to this:
var obj = {
conn : null,
first : function(thisIdentity) {
"use strict";
var mySelf = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
mySelf.conn = new Connection(data.user_id, "127.0.0.1:80");
}
});
},
second : function(thisIdentity) {
"use strict";
var mySelf = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
// now you can access the connection with mySelf.conn
}
});
}
};
The syntax itself is wrong. You are creating a variable or giving an expression inside an object literal. Remember this is not a function, but instead, it should be:
$.ajax ({
// computation and in success function
conn: new Connection(data.user_id, "127.0.0.1:80")
});
Updated
When you are giving such a way of definition:
success : function() {
this.conn = new Connection(data.user_id, "127.0.0.1:80");
}
Here, the this object refers to the success function and not your object. Read Understanding Scope and Context in JavaScript. Now you need to create a proxy variable for this and use it:
first : function(thisIdentity) {
"use strict";
var myObj = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
myObj.conn = new Connection(data.user_id, "127.0.0.1:80");
}
});
},

method with parameter in unknown js function issues

I'm trying to protect a part of my js code wrapping my code with an Unknown function.
I have edit my function to change
function banana(url) {}
to method
banana: function(url){ },
when I try to call my function banana in another function i try to use
this.banana(url);
but i have this error:
TypeError: this.banana is not a function
Full code:
(function (){
var url_test = "./add_user.php?opt=get_user&token=<?php echo $token; ?>";
if (typeof $.customfnc == 'undefined')
$.customfnc = {}
$.customfnc.get = {
setup: function (){
var url = "google.ca";
this.banana(url);
},
banana: function (url){
console.log("my url: " + url);
};
};
};
// on ready render data
$(document).ready(function() {
$.customfnc.get.setup();
});
})(jQuery);
thanks for your help!
The issue here is that the scope of 'this' is not exactly what you might think it is.
The way I have handled this particular issue in the past is to add
var self = this;
Outside of the object that is attempting to self reference. This may impact how you have set up youre .get() object though.
$.customfnc.get = function(){
var self = this;
self.setup = function (){
//....
self.banana(URL)
}
self.banana = function(url){
//...
}
}

How to call a function's methods from within another function

In the form object below, from within the "check" function, how do I call the "show" and "hide" methods of the notification function?
(function (namespace, $, undefined) {
var form = {
check : function(){
form.notification.show(); // Generates an error
},
notification : function(){
this.show = function(){
...
};
this.hide = function(){
...
};
}
};
}(window.namespace = window.namespace || {}, jQuery));
With form.notification.show() I get the following error:
Uncaught TypeError: Cannot read property 'show' of undefined
Try to define notification outside form and then refer to it:
var notification : { // no function here
show : function(){...}, // avoid "this"
hide : function(){...}
};
var form = {
check : function(){
notification.show(); // <-- Use here
},
notification : notification // and here
};
(I omitted the jQuery protection code for clarity).
The next problem is that you this.show = will assign the function to whatever this is when the function notification() is executed. this isn't notification!
You've enclosed it, so you need to return it and that will expose it for you, if you whip the following in chrome console, you'll see you have access to the form object
(function (namespace, $, undefined) {
var form = {
check : function(){
form.notification.show(); // Generates an error
},
notification : function(){
this.show = function(){
};
this.hide = function(){
};
}
};
return{form:form};}(window.namespace = window.namespace || {}, jQuery));
All i've done to your code is added
return{form:form};
After the form object. Hope this helps
EDIT
If you want to only expose certain parts of the form, for example only notifications, you could modify the return like so:
return{form.notification: notification}

Javascript OOP help/advice/explanation

Hey all I have a question. I'm writing a small Js Object to make it easier for me to manage what page I'm on in order for me to be able to load proper scripts/styles per page. I am running into a situation that I just dont understand. I have a property currentPage that will obviously enough be set to the current page but if I just set it straight from another property I previously defined, it returns a reference error, but if I put it into a function that returns the same thing, it works. I'm not sure why that is. Can someone explain this to me? I'm not a hardcore JS Developer I just figure things out as I go, so is this something specific to JS? Here's a code sample of what I mean :
var self = PageInfo = {
locationArray : window.location.pathname.toString().split("/"),
printOutPath : function(){
console.log(self.locationArray.length);
},
//ref. error to locationArray
parentDirectory : self.locationArray[self.locationArray.length -3],
currentPage : function() {
return self.locationArray[self.locationArray.length -2]; // works
}
};
When you use JavaScript object literal syntax (creating an object with the curly braces {}) the values that go with each property are expressions that get evaluated at the moment the object is created. They can't reference properties of that same object because the object doesn't exist yet.
Note that within your object's methods you can use this instead of creating the self variable. As long as you call the methods using dot syntax like this:
PageInfo.currentPage()
...within the method this will automatically reference the object so you can do this:
var PageInfo = {
locationArray : window.location.pathname.toString().split("/"),
printOutPath : function(){
console.log(this.locationArray.length);
},
currentPage : function() { return this.locationArray[this.locationArray.length -2];}
};
alert( PageInfo.currentPage() );
Further reading: https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects
When you define an object, you can't refer to the object until it has been created. By using a function, you're delaying the lookup of self.locationArray until the object has been created.
Object is assigned to self and PageInfo only after the execution of the statement.
So do it after the statement.
var self = PageInfo = {
locationArray : window.location.pathname.toString().split("/"),
printOutPath : function(){
console.log(self.locationArray.length);
},
currentPage : function() { return self.locationArray[self.locationArray.length -2]; // works
}
};
self.parentDirectory = self.locationArray[self.locationArray.length -3];
It will update PageInfo also
Use this inside functions to make it more OO
var self = PageInfo = {
locationArray : window.location.pathname.toString().split("/"),
printOutPath : function(){
console.log(this.locationArray.length);
},
currentPage : function() { return this.locationArray[this.locationArray.length -2]; // works
}
};
self.parentDirectory = self.locationArray[self.locationArray.length -3];
You can also create a function to set parentDirectory
var self = PageInfo = {
locationArray : window.location.pathname.toString().split("/"),
printOutPath : function(){
console.log(this.locationArray.length);
},
parentDirectory:"",
setParentDirectory: function() {
this.parentDirectory = this.locationArray[this.locationArray.length -3];
},
currentPage : function() { return this.locationArray[this.locationArray.length -2]; }
};
self.setParentDirectory();

Categories