Object within Prototype [duplicate] - javascript

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"

Related

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

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();

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}

Checking whether toString has been assigned [duplicate]

This question already has answers here:
How do I check if an object has a specific property in JavaScript?
(31 answers)
Closed 7 years ago.
I want a debugging output function to contain a test: if the object has a toString function, use it.
But then, every JavaScript object has a toString function, so what I really want is to check whether it has been assigned toString instead of just inheriting a default one.
What's the best way to do this? It occurs to me maybe you could exploit the fact that the inherited function isn't visible in for-in iteration, though it feels like there ought to be an O(1) solution.
something like
obj.hasOwnProperty('toString')
The result of obj.hasOwnProperty('toString') depends on the way how your toString implementation is created. I did some simple test:
function A() {
}
A.prototype.toString = function(){
console.log("A.toString");
};
function B() {
this.toString = function(){
console.log("B.toString");
}
}
var t = [new A(), new B(), new A()];
for(var i=0; i<t.length; i++) {
var hasOwnToString = t[i].hasOwnProperty("toString");
console.log(hasOwnToString);
if(hasOwnToString) {
t[i].toString();
}
}
Result:
false
true
B.toString
false
For A style it's false, but for B style it's true
You can check to see if the toString function is the same as Object (the object all objects descend from)
function hasUserPrototype(obj) {
return Object.getPrototypeOf(obj).toString !== Object.prototype.toString;
}
See Check if an object has a user defined prototype?
function Foo()
{
}
// toString override added to prototype of Foo class
Foo.prototype.toString = function()
{
return "[object Foo]";
}
var f = new Foo();
function Boo()
{
}
var g = new Boo();
function hasUserPrototype(obj) {
return Object.getPrototypeOf(obj).toString !== Object.prototype.toString;
}
document.write(hasUserPrototype(f)); // true
document.write(hasUserPrototype(g)); // false
var x = {}
if (!(x.hasOwnProperty("toString"))) {
x.toString = function() {
return "I am X"
}
}
x.toString()
// "I am X"

Place references to prototype method in prototype object as dictionary [duplicate]

This question already has answers here:
Organize prototype javascript while perserving object reference and inheritance
(3 answers)
Closed 7 years ago.
In my little brain I can't explain how to refer correctly to method in object's prototype:
function A(){}
A.prototype.action = function(){}
A.prototype.dict = { action: this.action } // Mistake here.
var a = new A();
a.dict.action(); // -> undefined, but I expect a call of 'A.prototype.action' or other function if I override it in 'a'
You haven't really explained why you need this functionality, but the following should help you avoid the errors you're seeing. Whether this is good practice or not I leave up to you to research.
function A() {
var self = this;
this.dict = {
action: function() {
// by default, A.dict.action calls A.action
return self.action();
}
};
}
// Define A.action
A.prototype.action = function() {
console.log('prototype');
};
// Let's test it out
var a = new A();
a.dict.action(); // prints 'prototype'
// Override it on instance a
a.dict.action = function() {
console.log('overridden');
};
a.dict.action(); // prints 'overridden'
// Let's create a new instance of A: b
var b = new A();
b.dict.action(); // prints 'prototpye'

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