jQuery: how to access parent function "this" from inside anonymous function? - javascript

...
$.fn.annotateEdit = function(image, note) {
if (note) {
this.note = note;
} else {
var newNote = new Object();
newNote.id = "new";
this.note = newNote;
}
}
...
var mynote = this.note;
form.find(':radio').change(function() {
var vacancy = $(this).attr('value');
mynote.vacancy = vacancy;
});
...
Is it possible to access "this.note" from the change() handler without defining "mynote"?

I use a pattern like this so I can access anything in the enclosing scope:
var that = this;
...
form.find(':radio').change(function () {
that.note.vacancy = $(this).attr('value');
});
I am a fan of this pattern because it makes the code a little more readable. In my opinion, it is clear what it being accessed is part of the enclosing scope (as long as the usage of that is consistent).

Use $.proxy to bind it to a function...
// Returns a function-------v
form.find(':radio').change( $.proxy(function() {
var vacancy = $(this).attr('value');
mynote.vacancy = vacancy;
}, this) );
// ^---- ...that has its "this" value set as this argument.

There is no dedicated language mechanism for it. The common pattern is to store the this in local (closure) variable (often named self or that) of the outer function:
var self = this;
var innerFunction = function() {
self.x = 1;
};

Check this - http://api.jquery.com/bind/ and "Passing event data"
You can do something like this :
form.find(':radio').bind("change", {
context : this
}, function(event){
console.log(event.data.context);
console.log(event.data.context.note);
});

You can bind the context of the parent object like so.
form.find(':radio').change(function(that) {
var vacancy = $(this).attr('value');
that.note.vacancy = vacancy;
}.bind(null,this));

Related

I want to call parent function into function which is wraped in object

Below is my code -
contactNumberMask: function(value) {
return value
},
componentDidMount: function() {
this.params = {
cellNumber: ''
};
var maskList = $.masksSort($.masksLoad("http://cdn.rawgit.com/andr-04/inputmask-multi/master/data/phone-codes.json"), ['#'], /[0-9]|#/, "mask");
this.maskOpts = {
inputmask: {
onMaskChange: function(maskObj, determined) {
if (determined) {
var number = this.contactNumberMask(maskObj.mask);
this.params.cellNumber = number+'-'+this.params.cellNumber;
}
}
};
},
In this i want to call this.contactNumberMask() function inside onMaskChange() function. but it is not getting reference of this.
Use bind() to set the context
onMaskChange: function(maskObj, determined) {
if (determined) {
var number = this.contactNumberMask(maskObj.mask);
this.params.cellNumber = number+'-'+this.params.cellNumber;
}.bind(this)
There's some ways to do. For example, storing the this reference in a variable.
contactNumberMask: function(value) {},
componentDidMount: function() {
var that = this;
this.params = {
cellNumber: ''
};
var maskList = $.masksSort($.masksLoad("http://cdn.rawgit.com/andr-04/inputmask-multi/master/data/phone-codes.json"), ['#'], /[0-9]|#/, "mask");
this.maskOpts = {
inputmask: {
onMaskChange: function(maskObj, determined) {
if (determined) {
var number = that.contactNumberMask(maskObj.mask);
this.params.cellNumber = number+'-'+this.params.cellNumber;
}
}
};
},
You have several choices :
create a variable self at the beginning of componentDidMount function
var self = this
Then you use self instead of this.
you can also create a function _onMaskChange and then use the bind method to set the 'this' in this method
onMaskChange: _onMaskChange.bind(this, maskObj, determined)
Your function(maskObj, determined) block won't have the same context (this) as the surrounding block. That's because - if not specified other - a function block will create its own context (this). The function is not bound to the outer context.
Multiple answers above are an option. But what I would recommend is using the => arrow function syntax. This will implicitly bind() your function to the outer context:
onMaskChange: (maskObj, determined) => {...}
Also it has a much cleaner syntax.

How can i use two different scope "this" in one function?

So i need to get the inner text of a given element through a Jquery event, and then set this text into a member of my class e.g.
myClass = function ()
{
this.index = 0;
this.onNavElementClick = function ()
{
this.index = parseInt(this.text());
}
this.myMain = function ()
{
$("nav#wow-so-much-inspiration").on("click", "a", this.onNavElementClick);
}
}
myObject = new myClass();
myObject.myMain();
HTML:
<nav id="wow-so-much-inspiration">
1
2
3
</nav>
But this won't work because of the two different scopes inside the onNavElementClick() function... And i don't like the idea of doing _this = this, i'm pretty sure there is a right way to do that without doing MacGyver coding.
jQuery event handlers also take the event object (including the target on which the event was triggered) as a first argument. Then you can use $.proxy to have your event handler bound to the outer this.
Something like this:
this.onNavElementClick = $.proxy(function (e)
{
this.index = parseInt($(e.target).text());
}, this);
You could make use of the bind method, but I believe this has been proven to have minor performance implications.
Example - which is essentially what the $.proxy answer does.
var myClass = function ()
{
this.index = 0;
this.onNavElementClick = (function (event) {
this.index = parseInt( $(event.target).text() );
}).bind(this);
this.myMain = function ()
{
$("nav#wow-so-much-inspiration").on("click", "a", this.onNavElementClick);
};
}
var myObject = new myClass();
myObject.myMain();
Another option is to use call or apply with a simple wrapper function.
var myClass = function ()
{
this.index = 0;
this.onNavElementClick = function (event)
{
this.index = parseInt( $(event.target).text() );
};
this.myMain = function ()
{
var self = this;
$("nav#wow-so-much-inspiration").on("click", "a", function (event) {
self.onNavElementClick.call(self, event);
});
};
}
var myObject = new myClass();
myObject.myMain();
Define onNavElementClick as a var within the my class constructor and reuse the function as needed.
var onNavElementClick = function(){...};

Using _self so I always can have object context

What is the proper way to use _self to always have access to an object? Is using _self ok, or is it bad practice?
I want a good way to get at myObject's attributes and methods, even from functions that aren't called in myObject's context. There are solutions like .bind(this), using _self, and jQuery's $.proxy().
For example:
var myObject = {
name: 'Tyrion',
alias: 'imp',
_self: function() {
return this;
},
// I know this context is fine, but let's pretend it's being called from elsewhere.
getAlias: function() {
var _self = myObject._self();
return _self.alias;
}
}
In order to do what you're looking to do, you'd have to change a few things. #elclanrs is right about what your this context is. I'll put two options below.
var myObject = {
name: 'Tyrion',
alias: 'imp',
// I know this context is fine, but let's pretend it's being called from elsewhere.
getAlias: function() {
// you'd have to do this in every method.
var _self = this;
return _self.alias;
}
}
The other option is a bit different, and not as usable, but I'm adding it so you can see it:
var myObject = function() {
var _self = this;
_self.name = 'Tyrion';
_self.alias = 'imp';
_self.getAlias = function() {
return _self.alias;
};
};
in the second instance, getAlias would be better as a prototype method, but you won't have access to the _self variable, only this.
You can do this too but I wouldn't necessarily recommend it.
var obj = {
_self: this.obj, // if you don't have .obj it points to window
thing: 'thingy',
alsoThis: function() {
return 'another thing'
}
};
obj._self;
It's also possible that since it's not within a closure, or a function in otherwords, the context of this._self may be incorrect if the context is changed by the scope which its referenced in.
Generally, I just do var _self = this; right before a function which I am nesting another function within that requires the this context outside the parent function since the nested one will not have the ability to access the value of this being nested.
That's usually not too common in my experience, and you really shouldn't be declaring such a property/var that needs to be used for the purpose that _self vars serve. It isn't a good practice and would be best to not do.
What if you run into a situation where you need to have _self = some other context?
thisis determined by the invocation of the function. (aka, the way the function is called) See my other answers for more details.
var myObject = {
name: 'Tyrion',
alias: 'imp',
_self: function () {
return this;
},
// I know this context is fine, but let's pretend it's being called from elsewhere.
getAlias: function () {
var _self = myObject._self();
return _self.alias;
}
};
//member invocation
console.log(myObject._self() === myObject); // true
var aFucntion = myObject._self;
//functional invocation
console.log(aFucntion() === myObject); // false
console.log(aFucntion() === this); //true
Instead of worrying about the context of this, a workaround is to assign this to a value in an outer function, and then access that value in an inner functions. This is called closure
var MyObject = function (title) {
var _self = this,
helper = function () {
return _self.title + " " + _self.name;
};
this.title = title;
this.fullName = function () {
return helper(); //functional invocation
//if helper used this, this would be global
};
this.name = 'Tyrion';
this.alias = 'imp';
this.getAlias = function () {
//access to _self through closure
return _self.alias;
};
};
//constructor invocation
var aObject = new MyObject("Mr.");
console.log(aObject.getAlias()); //imp
console.log(aObject.fullName()); //Mr. Tyrion
FYI:
If _self returns myObject, context would not mater.
_self: function () {
return myObject;
}

How to prevent jquery to override "this"

I have the following class in javascript:
function User(aJid){
this.jid = aJid;
this.name = '';
this.uni = '';
this.edad = '';
this.foto = '';
this.avatar = '';
this.initialize2 = function(){
$('#edit_vcards').on('click', '#enviar_vcard', function(){
//alert("enviando...");
console.log(this);
});
};
As you can see I have a method "initialize2" that binds a function to some elements in the DOM. In there I do a console.log(this) which prints the DOM element we binded the method to and not the object that is executing the method initialize2. How can I have access to that object from that function?
Its like if the scope of the function binded is the whole DOM and not the object. Anyway to do what Im trying to do ?
function User(aJid){
this.jid = aJid;
this.name = '';
this.uni = '';
this.edad = '';
this.foto = '';
this.avatar = '';
this.initialize2 = function(){
var that = this; //store a reference to maintain scope
$('#edit_vcards').on('click', '#enviar_vcard', function(){
//alert("enviando...");
console.log(that); //use that variable here
});
};
Try passing the obj this to .on and the inside the handler you can use event.data to access the obj this. See below,
this.initialize2 = function(){
$('#edit_vcards').on('click', '#enviar_vcard', {obj_this: this }, function(){
//alert("enviando...");
console.log(event.data.obj_this); //should be the obj this
});
};
Pass the outer this through event.data:
$('#edit_vcards').on('click', { outerThis: this }, function (event) {
console.log(event.data.outerThis);
});
Nowadays with ES6 it can be even more elegant
$('#edit_vcards').click( () => {
//alert("enviando...");
console.log(this); // all your variables are availabled here
});
or even like that (if you need only one line):
$('#edit_vcards').click( () => console.log(this) );
NOTE: This code cannot be used directly and should be additionally compiled with balel, for example.

how to get a reference to the defining 'class' inside an inner method in JavaScript?

I have the following JS code:
var Item = function ()
{
this.property = '';
this.myfunction = function ()
{
var value = this.property;
};
};
however, this does not point to the defining class so value doesn't get anything.
how do I access this.property from inside my function?
You need to create a closure which captures the value of parent scope's this:
var Item = function ()
{
this.property = '';
var self = this;
this.myfunction = function ()
{
var value = self.property;
};
};
Update: As others have pointed out, this closure is not needed when Item is used as a constructor (new Item()). Noting it here for future reference.
just create an alias for this. It will get closure'd.
var Item = function ()
{
this.property = '';
var self = this;
this.myfunction = function ()
{
var value = self.property;
};
};
Your code works as is if you call Item() as a constructor.
var item = new Item();
item.property = "the property";
item.myfunction(); // value = "the property"
this changes depending on the context. The context being how a function was invoked, not how it was defined, but how it was called.
Besides that, you seem to be mixing up two patterns here. I'm sure you meant something like:
var Item = function() {
this.property = '';
};
Item.prototype.myfunction = function() {
var value = this.property;
};
Instead you kind of mixed a closure pattern with prototypal, which doesn't seem very useful there. Closure is good for hiding members, allowing for true private members, but here you're exposing the property anyway. There's no reason not to stick that function on the prototype.
Do yourself a favor and ignore any concepts you have of more traditional OO, they won't do you any good here. Prototypal isn't nearly the same thing.

Categories