javascript Object - unreachable method [duplicate] - javascript

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
I have a javascript object with a handful of methods, and some of the methods reference each other. The methods become undefined in some situations, regardless of using the key word "this" with them. I'm not sure how to go about it. Here is a snippet of my object below. Method getContent() when accessed in onClickMngLinksBtn method becomes undefined when a button with onClickMngLinksBtn event binding is clicked. This same method works fine when accessed with:
InLineLinksObj.getContent()
I'm hoping the solution is something very basic to Objects in javascript. Any help is much appreciated.
function InLineLinks(formController, fieldController)
{
....
this.getContent = function(){
var field = this.getFieldController().getCustomFieldByName(this.content_field);
if(field){
return field.getValue();
}
return null;
};
this.onClickMngLinksBtn = function(){
var links = [];
var txt = this.getContent();
}
....
}

See here, here or here, or many other places for an explanation of scope and the this keyword in javascript. Essentially,
this always refers to the “owner” of the function we're executing
and when your method is triggered by a DOM event, then the owner is either the window or the HTML element that was clicked (or moused over, etc.), instead of the containing object.
A simple way around it in your case is to define a second variable self which will retain a reference to the containing object.
function InLineLinks(formController, fieldController) {
var self = this;
....
self.getContent = function(){
var field = self.getFieldController().getCustomFieldByName(self.content_field);
if(field){
return field.getValue();
}
return null;
};
self.onClickMngLinksBtn = function(){
var links = [];
var txt = self.getContent();
}
....
}

The way you have it, InLineLinks is a constructor and getContent is a method of it's instances.
Then, you must instantiate InLineLinks to reach getContent:
new InLineLinks().getContent()

Related

Referencing the Correct 'this' Without Re-declaring 'this' Inside Nested Functions [duplicate]

This question already has answers here:
Pass correct "this" context to setTimeout callback?
(6 answers)
Closed 6 years ago.
I have a class with multiple methods and properties. One of those methods has a setTimeout() function embedded in it as such:
function myClass() {
this.some_property = "test";
this.PrintOnTimeout = function() {
// I can do var.self = this;
// but I can't help but feel like that would be inefficient
setTimeout(function timeoutPrint() {
// I want to reference this.some_property here.
// Currently this.some_property returns an error as
// this refers to PrintOnTimeout() rather than myClass().
});
}
}
Apologies in advance if there's an answer up on StackOverflow. I've looked around but pretty much everything I find talks about extended classes and super(). Perhaps super() is the answer here and I'm not understanding it? I'd use global, but I'd prefer to treat each instance of this class as potentially unidentified. So if there's a this.GetMainParent or something... otherwise, I appreciate the uprgrade.
edit 1: The goal isn't to pass 'this' in, which is obvious, but instead to reference the main block (or any particular block, if you set it up so) from anywhere inside a set of nested functions.
edit 2: The arrow function was the solution I needed, as shown by ASDFGerte.
You can use an arrow function to bind this, use bind(this) or close over a local variable that stores the property.
Note that unless you bind this to every function involved, you need to make sure all related functions are always called in the correct context, otherwise you are binding the nested functions to the wrong this:
function a(){
this.x = "hi";
this.y = function() {
setTimeout(() => { console.log(this.x); }, 100);
};
}
let obj = new a();
let outside = obj.y;
obj.y(); //y is being called with this === obj
outside(); //y is being called with this depending on strict mode, window or undefined.

Ambiguous 'this' inside jquery callback [duplicate]

This question already has answers here:
"this" keyword in event methods when using JavaScript prototype object
(4 answers)
Closed 8 years ago.
My problem is the context of 'this' inside jquery callback.
$('input').on('change', function(){
this.number = $(this).val();
});
Above, this is the input element, which is normally what we want 'this' to be. The problem is that when it becomes a method of an object as below.
// constructor pattern
var View = function(){
this.number = 0;
};
// method definition
View.prototype.foo = function(){
$('input').on('change', function(){
// former this should be the object instance and
// the latter should be the html element.
this.number = $(this).val();
});
};
To change the context of this of the function, Function.bind() can be used as below.
View.prototype.foo = function(){
$('input').on('change', function(){
this.number = $(this).val();
}.bind(this)); // bind the callback to the instance of View object
};
Above works until $(this).val() since then $(this) wants the input element back not the View object.
In order to solve this in ad-hoc manner, I can explicitly set this to be the name of an instance as below.
View.prototype.foo = function(){
$('input').on('change', function(){
// explicitly set this to be the instance
// while sacrificing generality since code breaks when the object name is not 'view'
view.number = $(this).val();
});
};
var view = new View();
As you can see, this can resolve ambiguity of this but also compromises generality since code breaks when the object name is not 'view'.
Given above, how can I make the code resolve ambiguity while not compromising generality?
Please suggest a way. Thank you.
A common approach used in many lib/frameworks is as following:
View.prototype.foo = function(){
var self = this; // store this as a local variable
$('input').on('change', function(){
self.number = $(this).val();
});
};

Javascript: Object context lost when calling private function [duplicate]

This question already has answers here:
Javascript: Do I need to put this.var for every variable in an object?
(6 answers)
Closed 8 years ago.
i have a simple Javascript "class" im testing right now. I noticed that "this" in my private functions do not point to the object itself, instead, its pointing to the global scope (window).
Why?
Info: i want to keep mode private, so i used var mode instead of this.mode.
I also want to keep both internal functions private, so user has no access to it.
I basically use .prototype to add public functions to myStorage accessing private members with this.
My code:
var myStorage = function(mymode) {
var mode = mymode;
function privateFunctionA() {
// access this.mode to read mymode from constructor but
// this is pointing to window
};
function privateFunctionB() {
// access this.mode to read mymode from constructor but
// this is pointing to window
};
// check for indexeddb, websql and localstorage
if(mymode == 'A') {
privateFunctionA();
} else {
privateFunctionB();
}
};
myStorage.prototype.publicFunc = function() {
console.log(this.mode); // does this work?
}
var data = new myStorage();
this is always function scoped in JavaScript (unless you pass in a context explicitly using call() or apply(). Therefore, in your private functions, this no longer refers to the same this as in the parent scope. An idiomatic way of handling this in JavaScript is to assign this to a self var in the parent scope. E.g.,
var myStorage = function(mymode) {
var self = this;
var mode = mymode;
function privateFunctionA() {
console.log(self);
};
...
};
Regarding this snippet:
myStorage.prototype.publicFunc = function() {
console.log(this.mode); // does this work?
}
You will need to assign mode to this back in your constructor (instead of as a var). So, the constructor would now become:
var myStorage = function(mymode) {
var self = this;
this.mode = mymode;
function privateFunctionA() {
// works
console.log(self.mode);
};
...
};
And this.mode will also work in your .publicFunc() in this case.
As one more stylistic note, constructor functions in JavaScript usually use proper camel case (i.e., MyStorage).
I dont think you can access the object itself with this when using prototype, because the scope changes and you loose the reference to the primary object itself, so this becomes the window instead.
Check this other question in order to get some more info:
Use of 'prototype' vs. 'this' in JavaScript?
Hope this helps.

Is there any way to specify which 'this' I want to use in a JS anon function, similar to how Java does it?

I've come across this problem a few times, and I'm wondering if it can be solved without having to bind the anon function to 'this' in the context of the parent object.
Here is my situation:
I have an array-like object, lets call it 'numline', which implements an 'each' method. It is contained within another instance of an object, lets call it 'numtank'. The current code looks something like this:
function Numtank(numline) {
this.numline = numline;
};
Numtank.prototype.charForElem(elem) {
return "Number: " + elem;
}
Numtank.prototype.toString() {
var str = "";
this.numline.each(function(elem) {
str += this.charForElem(elem); //But 'this' is called in the contex of the 'numline' instance, which dosen't (and shouldn't) have the charForElem class.
});
return str;
}
var tank = new Numtank(arbatraryNumline);
tank.toString(); //Uncaught ReferenceError: charFromElem is not defined in numline
When I ask 'similar to how Java does it', I mean how Java allows you to prepend the class name to 'this' to specify which 'this' to use.
Is there anyway to get around this without having to bind the anonomouns function to this?
What is generally done is to hold a reference called self. It is the most common practice.
Numtank.prototype.toString() {
var self = this, str = "";
this.numline.each(function(elem) {
str += self.charForElem(elem);
});
return str;
}
You can save a copy of this in another variable.
var oldThis = this;
The variable will be visible to those nested callback functions.

What is the difference between myObject.someFunc = function(){...}; or myObject.prototype.someFunc = function(){...} in javascript? [duplicate]

This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Prototyped and a non-prototyped method? [duplicate]
(1 answer)
Closed 8 years ago.
Suppose I create an object in javascript.
var myObject = {};
What is the difference between...
myObject.someFunc = function(){...};
and
myObject.prototype.someFunc = function(){...}
in javascript?
I am having trouble understanding the difference or if there is a difference and how and when to use either of these syntaxes.
It seems when I code something like this that there really is no difference.
I am looking for both a client side (browser) and server side (like node.js) answers.
I want to code properly and accurately and this is really bothering me.
In this case:
var myObject = {};
myObject.someFunc = function(){...};
All you're doing is creating a plain object, which happens to have a property which is a reference to a function. This is often done just for name spacing, i.e. to group a whole load of functions in one place under a common object.
Note however that var myObject = {} doesn't actually have a prototype so your second example is impossible.
For an object to have a prototype it must be the result of a constructor function, i.e.
function MyObject() {
...
}
MyObject.prototype.someFunc = function() { }
var myObject = new MyObject();
// myObject.someFunc can now be used
The prototype is a property of the constructor function - not of any instance of that class.
If you put the function on the prototype only one instance of the function object exists and will be shared by all instances of the class. This is more memory efficient that having a copy on each instance.
All of this applies regardless of whether the code is in a browser or on a server - it's still the same language.
Essentially this represents a static method (or a method attached to only that object (myObject in this case):
myObject.someFunc = function () {...};
This represents a method attached to the prototype of the object (an instance method):
myObject.prototype.someFunc = function () {...};
myObject.someFunc = function(){...} is a one time instance of that function, who's return value is being assigned to the someFunc property of myObject.
myObject.prototype.someFunc = function(){} is actually creating a method that can be called anywhere on myObject and will change the same instances of values each time.
myObject.prototype.someFunc = function(num){
this.num_to_be_stored = num;
}
will change the value of num_to_be_stored not someFunc which is what is happening in the first instance.
edit: sorry early morning was not clear on what I was trying to say.

Categories

Resources