How to call a JavaScript object method from within a method [duplicate] - javascript

This question already has answers here:
OOP. Calling methods from within methods
(4 answers)
Closed 8 years ago.
I'm just trying to figure out how I can call a javascript object method from within a method of the same object as below..
var testObject = {
method1 : function() {
var connectionAddr = "ws://localhost:8003";
socket = new WebSocket(connectionAddr);
socket.onmessage = function(event) {
method2();
}
},
method2: function() {
this.method1();
}
}
Changed my question as I realise when using this.method2() it is refering to the WebSocker object.

There are a lot of answers in SO for problems like this, you should do a little research(on SO or on Google) before asking here.
var testObject = {
method1 : function() {
var connectionAddr = "ws://localhost:8003",
self = this;
socket = new WebSocket(connectionAddr);
socket.onmessage = function(event) {
self.method2();
}
},
method2: function() {
this.method1(); //something like this would cause an infinite call stack, you should change this code
//this refers to the current object, so has properties method2 and method2
}
}
You need to reference to the current object using this, otherwise the JS Engine will look for a function named method1 in any of the higher scopes, all the way up to the global namespace. If such a function object (or such a name doesn't exist), method1 will be evaluated to undefined.

try this
var testObject = {
method1 : function() {
var connectionAddr = "ws://localhost:8003";
socket = new WebSocket(connectionAddr);
socket.onmessage = function(event) {
testObject.method2();
}
},
method2: function() {
testObject.method1();
}
}

updated to match your current question: good part is you can add additional functions and call any one of them with this method;
var testObject = {
method1 : function() {
var connectionAddr = "ws://localhost:8003",
self = this;
socket = new WebSocket(connectionAddr);
socket.onmessage = function(event) {
self['method2']();
}
},
method2: function() {
this['method1']();
}
}

Related

this keyword and function scope in javascript [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 6 years ago.
I have the following code (simplified)
var Page = new UI('page.html');
Page.onLoad = function(html){
this.name = 'Page 1';
Util.test(this.run);
};
Page.run = function(){
console.log(this.name); // undefined
console.log(Page.name); // correct
};
var Util = function(){};
Util.prototype.test = function(callback){
// when finished run the callback
callback();
};
My question is why I can't use the this keyword if the execution leaves the object then comes back? Please explain what should I change to be able to access this again.
You can bind "this" to function run, like this.
Page.onLoad = function(html){
this.name = 'Page 1';
Util.test(this.run.bind(this));
};
You can find more information for function "bind". https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
The top of the article references another post regarding 'this', so, I thought I'd just provide the code. If you read the other post and the articles linked within, you should be able to follow this code.
function UI(html) {
this.name = html;
}
UI.prototype = {
onLoad: function () {
util.test(this);
},
run: function () {
console.log(this.name);
}
}
var util = (function () {
return {
test: function (ui) {
if (ui && ui.run) {
ui.run();
}
}
}
})();
var page = new UI("index.html");

Why did my callback lose its scope? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
When test.testHello(helloWorld.sayHello); runs, it doesn't recognize that I have inserted a new greeting is the greeting is undefined. I can use bind to make sure it runs it in the proper scope, I am not really sure why isn't it running in the proper scope to begin with. Could someone explain why this is happening and show me a better solution?
Solution: test.testHello(helloWorld.sayHello.bind(helloWorld));
http://jsfiddle.net/EzabX/
var HelloWorldClass = function() {
this.greetings = [];
}
HelloWorldClass.prototype.addGreeting = function(greeting) {
this.greetings.push(greeting);
}
HelloWorldClass.prototype.sayHello = function() {
document.getElementById('output').innerHTML += this.greetings;
this.greetings.forEach(function(greeting) {
greeting.execute();
})
}
var TestClass = function() {
this.testHello = function(callback) {
alert("TestHello is working, now callback");
callback();
}
}
var main = function() {
var helloWorld = new HelloWorldClass();
var test = new TestClass();
helloWorld.addGreeting({
execute: function() {
alert("Konichiwa!");
}
});
helloWorld.sayHello();
test.testHello(helloWorld.sayHello);
}
main();
Managing the this variable within the prototype function scope when called as a callback can be complicated for novice users. You don't always need a prototype for all functions on a class. If you really want to use a prototype function look at Javascript .bind(this) implementations. Google and Stackoverflow are your friend on that topic. Example: Preserving a reference to "this" in JavaScript prototype functions
Offending code with this referring to DOM Window object and not a HelloWorld instance:
this.greetings.forEach(function(greeting) {
greeting.execute();
})
A non-prototype version that works just great, easy to use. Fiddle: http://jsfiddle.net/EzabX/2/
var HelloWorldClass = function() {
var greetings = [];
this.greetings = greetings;
this.addGreeting = function(greeting) {
greetings.push(greeting);
};
this.sayHello = function() {
document.getElementById('output').innerHTML += greetings;
greetings.forEach(function(greeting) {
greeting.execute();
})
}; }

Add function to object

I have the following code
var PROMO = PROMO || {};
PROMO.Base = (function () {
var _self = this;
var Init = function () {
WireEvents();
};
var WireEvents = function () {
//wire up events
};
} ());
In the same file I have the code to call the above function
I am trying to get to an end point where I can use the following code
$(document).ready(function () {
PROMO.Base.Init();
});
this gives the error
Cannot call method 'Init' of undefined
Now I know there are many ways to write javascript, but in this case I want to be able to call my functions, or least the Init method in the way shown above.
var PROMO = PROMO || {};
PROMO.Base = (function () {
var _self = this;
var Init = function () {
WireEvents();
};
var WireEvents = function () {
//wire up events
};
var reveal = {
Init: Init
};
return reveal;
} ());
You need to return the public facing functions. See updated code.
Working fiddle with both patterns, using IIFE and direct attribution.
Using var makes the definition private and your function is returning nothing. Use this:
PROMO.Base = {
Init: function() {
},
WireEvents: function() {
};
};
You are wrapping the definition with an IIFE(Immediately Executed Function Expression). So your PROMO.Base object will be assigned the value of that (function(){//blabla})(); returns. But your function doesn't have a return statement. By default it will return undefined.
Which is way your PROMO.Base will be undefined and you get this:
Cannot call method 'Init' of undefined
If you really want that IIFE:
var PROMO = PROMO || {};
// NEVER use _self = this inside static functions, it's very dangerous.
// Can also be very misleading, since the this object doesn't point to the same reference.
// It can be easily changed with Function.prototype.call and Function.prototype.apply
PROMO.Base = (function () {
_PROMO = {
Init : function () {
document.body.innerHTML += "itworks";
},
WireEvents : function () {
//wire up events
}
}
return _PROMO;
} ());
PROMO.Base.Init();
Update
The better and easier pattern is to simply assign the functions to PROMO.Base. Dully note you should not capitalize static functions, but only constructors. So if something is not meant to be instantiated, don't call it Init, it should be init. That is the convention.
var PROMO = {};
PROMO.Base = {};
PROMO.Base.init = function() {
console.log("this works");
};
PROMO.Base.wireEvents = function() {
console.log("this is a static function too");
};
You can attach it to the window object like ...
window.PROMO = (function($, _){
// this will access PROMO.Base
PROMO.Base = {
// inner functions here
Init:{}
};
})(jQuery, _);
Then load it as you do.
Or if you depend from jQuery
(function($){
var PROMO = {
// inner functions
Init: function(){},
WireEvents: function(){}
};
$.PROMO = PROMO;
})(jQuery);
On DOM ready
jQuery(function ($) {
var promo = $.PROMO || undefined;
promo.Base.Init();
});

Callback this context [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
in App:
var bootstrap = new Bootstrap();
bootstrap.init( this, this.onBootstrapComplete );
in Bootstrap:
this.init = function( app, completeHandler ){
_app = app;
_completeHandler = completeHandler;
...
}
...
var _allReady = function(){
_completeHandler( _app );
}
back in App:
this.onBootstrapComplete = function( app )
{
app.something();
app.someValue = ...
}
I wanted to get this context inside onBootstrapComplete.
It works but it doesn't look right :)
If let's say I wanted to call onBootstrapComplete directly from App, I would have to call it this.onBootstrapComplete( this ).
How can I do it so my onBootstrapComplete looks like this:
this.onBootstrapComplete = function()
{
this.something();
this.someValue = ...
}
I would recommend using underscore.js. See http://underscorejs.org/#bind for further information.
this.onBootstrapComplete = _.bind( function() {
...
this.someFunction(); // this context is available now
...
}, this );
this is evaluated when the function is called. Say you use this inside a function f.
There are basically two ways to call f:
(expr).f() if f is called as a property on some object, this will evaluate to that object expr.
f() In this case, this will evaluate to window.
Since you pass the function to bootstrap, it can only call the function as f().
You could use a closure:
var self = this;
this.onBootstrapComplete = function()
{
self.something();
self.someValue = ...
}
Alternatively, you can use a function to f.apply() the function appropriately:
function bind(context, f){
return function() {
return f.apply(context, arguments);
}
}
this.onBootstrapComplete = bind(this, function()
{
this.something();
this.someValue = ...
});
Or with ECMAScript 5, there is already a bind function[MDN]:
this.onBootstrapComplete = function()
{
this.something();
this.someValue = ...
}.bind(this);

How can i call AnotherSubFunction using my obj

var obj = {
MainFunction: function() {
AnotherSubFunction: function() {
}
var variable = AnotherSubFunction ()
}
}
Can i do something like this...
How can i call AnotherSubFunction using my obj? Is it possible.
How to create a function inside another function...
The code in your question is not valid Javascript. You're probably looking for:
MainFunction: function() {
function AnotherSubFunction() {
// ...
}
var variable = AnotherSubFunction();
}
Or maybe:
MainFunction: function() {
AnotherSubFunction = function() {
// ...
}
var variable = AnotherSubFunction();
}
However, in both cases, the name AnotherSubFunction associated with the nested function only exists in the scope of the enclosing function (MainFunction) and will not be accessible directly from obj.

Categories