Access parent class variable from method, used by another class [duplicate] - javascript

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 3 years ago.
I have two classes which are not related:
class A {
myVar = null;
myFunc() {
console.log(this.myVar)
}
}
class B {
constructor(func){
this.func = func;
}
callFunc() {
this.func();
}
}
My problem is the following:
let a = new A();
let b = new B(a.myFunc);
b.callFunc();
This will be undefined because this in console.log(this.myVar) won't refer to the instance of class A, but the instance of class B. How can I access the global variable of class A when calling the function from another class?

You could use a.myFunc.bind(a), specifying that you want myFunc's this to refer to the a instance.
The bind() method creates a new function that, when called, has its this keyword set to the provided value
Also, don't forget your new operators :)
class A {
myVar = "Hello world";
myFunc() { console.log(this.myVar) }
}
class B {
constructor(func){ this.func = func; }
callFunc() { this.func(); }
}
let a = new A();
let b = new B(a.myFunc.bind(a));
b.callFunc();

Related

How do I reference class variables/methods from nested functions? [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
How to access the correct `this` inside a callback
(13 answers)
Closed 5 years ago.
class Foo {
constructor() {
this.foobar = "foobar";
}
bar() {
let _this = this;
return function() {
try {
alert("Attempt 1: "+foobar);//ReferenceError: foobar is not defined
myMethod();
} catch(err) {console.log(err);}
try {
alert("Attempt 2: "+this.foobar);//TypeError: this is undefined
this.myMethod();
} catch(err) {console.log(err);}
try{
alert("Attempt 3: "+_this.foobar);//Works!
_this.myMethod();
} catch(err) {console.log(err);}
}();
}
myMethod() {
alert("myMethod()");
}
}
new Foo().bar();
The above example is very simplified - the anonymous function inside bar() was a jQuery call originally, but for the sake of the question I didn't include that.
Why don't attempts 1 and 2 work? Do I have to use the _this trick to reference class variables/methods? How do I reference class variables/methods from nested functions?
Are you familiar with how the this keyword works in JavaScript? It's value will depend on how the function is called, not in how it is defined. For example, if you do the following:
var dog = {
greeting:"woof",
talk:function (){
console.log(this.greeting);
}
};
var cat={
greeting:"meow",
talk:dog.talk
};
dog.talk();
cat.talk();
You will see that when the talk function is called as a method of an object, that object will be used as the value of this.
The same happens with ES6 classes, where class methods are still JavaScript functions and the rules for deciding the value of this still apply. If you want to avoid declaring an auxiliar variable, you should look into using bind:
var mammal = {
greeting:"<noise>",
getTalk:function (){
return function(){
console.log(this.greeting);
};
},
getTalkBinded:function (){
return (function(){
console.log(this.greeting)
}).bind(this);
}
};
var dog={
greeting:"woof",
talk:mammal.getTalk(),
talkBinded:mammal.getTalkBinded()
};
var cat={
greeting:"meow",
talk:mammal.getTalk(),
talkBinded:mammal.getTalkBinded()
};
dog.talk();
cat.talk();
dog.talkBinded();
cat.talkBinded();
You are returning self-execution function execution result and during that function execution this it global context(not your class object). to make it work use () => {}() arrow function call syntax, as it captures current context, or function() { }.bind(this)().
See this simple example,
function a(){
this.someProp = 5;
console.log(this);
var _this = this; //so we explicitly store the value of `this` to use in a nested function
return function(){
//value of `this` will change inside this function
this.anotherProp = 6;
console.log(this);
//to use the methods and props of original function use `_this`
console.log(_this)
}
}
var c = a.call({}) //prints {someProp: 5}
c.call({}) //prints {anotherProps: 6} {someProp: 5}

How to keep context in javascript methods after call ajax? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
hi i have a problem with es6 and in particulary the methods of class. See my exemple :
my first class :
class A{
constructor(){
this.B = new B();
this.test = 5;
}
methodA1(){
B.methodB1(this.methodA2);
}
methodA2(){
console.log(this.test);
}
}
the second class :
class B{
methodB1(callback){
$.get("url",function(data){
...
callback();
});
}
}
When you execute methodA1, the code return : this is undefined (in a methodeA2) !
In fact when you call a callback function in ajax call the callback lost the context of class. Somebody have an idea to skirt this problem ?
Thanks.
You can use .bind to bind this.
methodA1(){
this.B.methodB1(this.methodA2.bind(this));
}
You get an error because you are not correctly referencing the B property you created in your constructor.
If you are sure that you'll be invoking methodA1 in the context of class A, then you can refer to property B by this.B. The this conext would point to the reference of the class A where B exists:
class A{
constructor(){
this.B = new B();
this.test = 5;
this.methodA2 = this.methodA2.bind(this);
// I prefer to bind my methods in the constructor so they are bound once
}
methodA1(){
this.B.methodB1(this.methodA2);
// ^ -- the B property created in constructor B exists as a property
// of this class, to reference it within a class method you need
// to call this.B
}
methodA2(){
console.log(this.test);
}
}
class B{
methodB1(callback){
$.get("url",function(data){
...
callback();
});
}
}
const a = new A();
a.methodA1(); // will log out 5 when the `$.get` request has its callback invoked

Object within Prototype [duplicate]

This question already has answers here:
Nested Object Literal Access Parent
(3 answers)
Closed 6 years ago.
I have created an object within a prototype and I am trying to access a variable from the constructor with this, but the alert is returning undefined.
Constructor
function Example() {
this.param1 = 'test';
}
Prototype
Example.prototype = {
constructor: Example,
obj: {
sample:function() {
alert(this.param1); // error undifined
}
}
};
Instantiate
var o = new Example();
o.obj.sample();
Any advice would be much appreciated.
You can do this though
function Example() {
this.param1 = 'test';
}
Example.prototype = {
constructor: Example,
obj: {
sample:function(){
alert(this.param1); // error undifined
}
}
};
var o = new Example();
o.obj.sample.call(o); // <--- I use "call" to supply the context. In this case, the context would be "o"
// or
o.obj.sample.bind(o)(); // or "bind" the context, in this case "o"

How to circumvent the ES6 Class scoping issue with 'this' key word [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
How do I write a named arrow function in ES2015?
(8 answers)
Closed 7 years ago.
For example in the Class constructor:
Socket.on('user:join', onUserJoin);
'onUserJoin' is declared as a method of the class but is being called by socket.io so the 'this' is not my Class. A way to resolve this is to use the '=>' function.
example:
Socket.on('user:join', (data)=>{
this.isOnline = true;
});
Now 'this' is my class, but how do I reference this anonymous function to unsubscribe ?
socket.removeListener('user:join', ????);
I did try this:
let self;
class RoomController {
constructor() {
self = this;
}
...
}
and reference the self in the methods but the self was being shared across sockets...
naming the anonymous function could solve it but I preferred for my case the bind option.
You can use Function.prototype.bind.
Socket.on('user:join', onUserJoin.bind(this));
This ensures that onUserJoin has the correct context, which will be the instance of your class.
You can always bind the arrow functions to the names.
For example,
class RoomController {
constructor() {
this.flag = true;
}
// Assign the arrow function to the name `setFlag`
setFlag = (v) => this.flag = v;
}
let r = new RoomController();
function tester(func) {
func(false);
console.log(r.flag);
// false
func(true);
console.log(r.flag);
// true
}
// Now you can pass the function around, `this` will still refer the object `r`
tester(r.setFlag);

How to access class variables from inner prototype - javascript [duplicate]

This question already has answers here:
'this' in function inside prototype function [duplicate]
(8 answers)
Closed 7 years ago.
I might not be clear with my title of the question. Sorry for that.
Here is what I wanted to do.
I'm trying to use prototyping pattern in javascript. I created a class as following.
var MyClass = null;
(function() {
MyClass = function() {
this.clsVar = "I'm inside constructor";
};
MyClass.prototype = {
constructor: MyClass,
myFunc1: function() {
console.log("I'm func1 accessing constructor variable : " + this.clsVar);
},
nested: {
myFunc2: function() {
console.log("I'm func2 accessing constructor variable : " + this.clsVar); // I know, this will never point to the class scope
}
}
}
}())
I'm creating an object.
var my = new MyClass();
my.myFunc1(); // which prints "I'm func1 accessing constructor variable : I'm inside constructor"
my.nested.myFunc1(); // as expected, it prints "I'm func2 accessing constructor variable : undefined
All I am trying to do is, I should be able to access clsVar from nested.myFunc2
is that possible.? Any help is greatly appreciated and needed.
Thanks.
Actually, there is a point.
The this inside your myFunc2 does not refer anymore to MyClass but to another context. So, the fastest way is to do is to use call or apply like:
var myNewObject = new MyClass();
myNewObject.nested.myFunc2.call(myNewObject, arg1, arg2);
or
myNewObject.nested.myFunc2.apply(myNewObject, [arg1, arg2]);
JavaScript's prototype-based class system does not allow this.
MyClass's prototype will be shared between all instances of the class. In the following code, both instances will use the same function instance...
var first = new MyClass(), second = new MyClass();
first.nested.myFunc2(); <-- Same prototype function
seecond.nested.myFunc2(); <-- Same prototype function
When the code enters the "myFunc2" definition, which parent should it be accessing?
If you need access to the parent's "this" value, you'll have to use a closure and set up the nested object in the parent constructor as below.
var MyClass = null;
(function() {
MyClass = function() {
this.clsVar = "I'm inside constructor";
var that = this;
this.nested = {
myFunc2: function() {
console.log("I'm func2 accessing constructor variable : " + that.clsVar); // I know, this will never point to the class scope
}
}
};
MyClass.prototype = {
constructor: MyClass,
myFunc1: function() {
console.log("I'm func1 accessing constructor variable : " + this.clsVar);
}
}
}())

Categories