Function inside an object gets wrong context - javascript

I have a constructor:
var ProfileDialog = function (containerObj) {
this.init = function () {
this.container = containerObj;
let content = document.createElement('div');
content.innerText = 'Dialog here';
this.container.appendChild(content);
this.container.style.display = 'none';
};
this.init();
};
Then I am extending the prototype of the constructor like this:
ProfileDialog.prototype.open = function () {
this.container.style.display = 'block';
}
var dlg = new ProfileDialog(document.body)
dlg.open();
This works fine, but if I try to put .open() inside an object like this:
ProfileDialog.prototype.actions = {
open: function () {
this.container.style.display = 'block';
}
}
var dlg = new ProfileDialog(document.body)
dlg.actions.open();
It fails with an error
functional.js:25 Uncaught TypeError: Cannot read property 'style' of undefined(…)
because of the wrong context passed to the function.
How do I make sure that independently of the nesting, context would be always the instantiated object?

Can you try binding 'this' to actions.open

Maybe you save this to that before and take it as a closure for the init function.
var ProfileDialog = function (containerObj) {
var that = this;
this.init = function () {
that.container = containerObj;
let content = document.createElement('div');
content.innerText = 'Dialog here';
that.container.appendChild(content);
that.container.style.display = 'none';
};
this.init();
};

Related

Passing object to a function and accessing its properties in JavaScript

I am new to prototype model coding in JavaScript.
I am trying to access properties($owl_nav and $owl_dots) of an object(elements) by passing the object to a function(setOverflowWrapperHeight), in code
function setOverflowWrapperHeight(elem) {
var owl_dots_height = elem.$owl_dots.height();
var owl_nav_height = elem.$owl_nav.height();
$('.overflow-wrapper').height(owl_dots_height + owl_nav_height + 150);
}
function NextQ(elements) {
this.checked_input = elements.checked_input;
this.$owl_ques_carousel = elements.$owl_ques_carousel;
this.$owl_nav = elements.$owl_nav;
this.$owl_dots = elements.$owl_dots;
this.init();
}
NextQ.prototype.init = function () {
this.bindEvents();
};
NextQ.prototype.bindEvents = function () {
var _this = this;
this.$owl_ques_carousel.on('click', '.nutrition_assessment_next_quest', function (event) {
_this.$owl_ques_carousel.on('translated.owl.carousel', function (event) {
setOverflowWrapperHeight(elements);
});
});
$(function () {
var $user_meta_div = $('div.user_meta_data_div');
setOverflowWrapperHeight($user_meta_div);
/***** NextQ Object *****/
elements = {
$owl_ques_carousel: $('.owl-carousel#ques-carousel'),
checked_input: true,
$owl_nav: $('.owl-nav'),
$owl_dots: $('.owl-dots')
};
/***** Create instance of NextQ Function *****/
nextQ = new NextQ(elements);
});
But the console outputs this error:
Uncaught TypeError: Cannot read property 'height' of undefined
I want to know if this is even legal. If yes, where am I going wrong?

Get "this" context in a JS "class" method function

I am trying to create a "class" in JS, a simplified structure of which is below:
http://codepen.io/Deka87/pen/WpqYRP?editors=0010
function Alert() {
this.message = "Test alert";
this.document = $(document);
this.document.on('click', function() {
this.show();
}.bind(this));
};
Alert.prototype.show = function() {
setTimeout(function() {
console.log(this.message);
}, 50);
};
var alert = new Alert();
When you click on the document it should show you the this.message contents in console. However, it is now shown as undefined. I believe the problem is that this.messsage can't get the original this context because it is wrapper in another function (setTimeout in my case). Any help would be appreciated!
Here's what worked for me, you get your this.message by referencing self, which is the correct context you need.
function Alert() {
this.message = "Test alert";
this.document = $(document);
this.document.on('click', function() {
this.show();
}.bind(this));
};
Alert.prototype.show = function() {
var self = this;
setTimeout(function() {
console.log(self.message);
}, 50);
};
var alert = new Alert();
You can use arrow functions which will preserve your this context.
function Alert() {
this.message = "Test alert";
this.document = $(document);
this.document.on('click', () => {
this.show();
});
};
Alert.prototype.show = function () {
setTimeout(() => {
console.log(this.message);
}, 50);
};
var alert = new Alert();
Read more: https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Functions_and_function_scope/Arrow_functions.

How to initialize a class object in Javascript

I have a Javascript class say "myjavascript.js". I have the following class:
var myClass= function () {
this.property2 = '';
this.property3 = '';
this.property4 = '';
this.property5 = '';
this.say() = function () {
alert('Say Hello');
}
I have a function which is triggered on some event.
function myFunction(){
var myClassObj= new myClass();
myClassObj.property2 = 'property2' ;
myClassObj.property3 = 'property2' ;
myClassObj.property4 = 'property2' ;
myClassObj.property5 = 'property2 ';
myClassObj.say();
}
On triggering function I am getting the this error
Uncaught TypeError: undefined is not a function
Keep in mind both are in the same file.
this.say() is the error. You are calling the function, not defining it.
this.say = function () {
alert('Say Hello');
}

Calling function inside javascript class functions?

I am trying to declare properties and functions to a specific js class. But when I try to call function inside a function (even if called after declared) it throws a exception
Uncaught TypeError: Object [object Object] has no method 'addButtonEventListeners
My code listed: SplashScene.js
var anim1, background;
var SplashScene;
function SplashScreen(SceneContainer)
{
this.name = "SplashScreen";
this.loadScreen = function()
{
background = new createjs.Shape();
background.graphics.beginBitmapFill(loader.getResult("gameLoopSplash")).drawRect(0,0,w,h);
SplashScene = new createjs.Container();
anim1 = new createjs.Sprite(buttonData, "playIdle");
anim1.framerate = 30;
anim1.x = 260;
anim1.y = 22;
SplashScene.alpha = 0;
SplashScene.addChild(background);
SplashScene.addChild(anim1);
}
this.addButtonEventListeners = function()
{
console.log("addButtonEventListeners SplashScreen" );
}
this.menuIn = function()
{
console.log("menuIn SplashScreen" );
stage.addChild(SplashScene);
var tween = createjs.Tween.get(SplashScene).to({y : 0, x : 0, alpha : 1}, 5000).call(this.menuInCompleted);
var splashTimer = window.setTimeout(function(){menuOut("MainScreen", false)},15000);
}
this.menuInCompleted = function()
{
console.log("menuInCompleted SplashScreen" );
this.addButtonEventListeners();
}
}
Can anybody tell me how can I do this?
The problem is that the context (this) in the setTimeout callback is window, not your object.
You can change
var splashTimer = window.setTimeout(function(){menuOut("MainScreen", false)},15000);
to
var splashTimer = window.setTimeout(
(function(){menuOut("MainScreen", false)}).bind(this)
,15000);
and you also have to do the same where you bind menuIn (to an event?).
Your problem is this, which points to the current context (in runtime) and not to your object's one.
Just add a variable in SplashScreen like:
var self=this; //keeping the context of SplashScreen
And then call it as follows:
this.menuInCompleted = function()
{
console.log("menuInCompleted SplashScreen" );
self.addButtonEventListeners ();
}

anonymous event handler doesn't have access to prototype method

Can't access fx1 from fx2 inside an anonymous function handler?
var MyComponent = function () {
//my constructor
}
MyComponent.prototype.fx1 = function() { //code }
MyComponent.prototype.fx2 = function() {
var btn1 = document.getElementById('Button1')
btn1.onclick = function() {
//issue is here
//trying to call fx1 from here but can't access it.
this.fx1(); //doesn't work.
}
}
As this is bound to the button within the onclick handler, you cannot use it to access the MyComponent instance. But you can simply save the reference in another variable which you then can use:
MyComponent.prototype.fx2 = function() {
// save reference to the instance
var self = this;
var btn1 = document.getElementById('Button1')
btn1.onclick = function() {
// access the saved reference to the MyComponent instance
self.fx1();
}
}
Another way to do this:
MyComponent.prototype.fx2 = function() {
var btn1 = document.getElementById('Button1');
btn1.onclick = (function() {
this.fx1();
}).bind(this);
}

Categories

Resources