This question already has answers here:
jquery using this to access object context when inside callback
(3 answers)
Closed 8 years ago.
I have a class Playlist :
function Playlist() {
this.episodes = [ /*episode list*/ ];
};
and I want to make a method displaying each episode :
Playlist.prototype.display = function() {
$('.episodeList').each(function(index) {
$(this).children('title').text(this.episodes[index].title);
});
}
The problem is that the 'this' at the end, before '.episodes[index]' represent the dom object selected and not my playlist.
How can I solve this problem ? Thanks.
Bind the function to your context:
$('.episodeList').each($.proxy(function(index, elem) {
$(elem).children('title').text(this.episodes[index].title);
}, this));
More on jQuery.proxy
If you use each on dom element, this inside each have reference to dom elements
For example:
Playlist.prototype.display = function(e)
{
$('.episodeList').each(function(index) {
console.log(this)
});
}
console.log prints dom element and it is correct.
Now put console log outside each like this:
Playlist.prototype.display = function(e)
{
console.log(this)
$('.episodeList').each(function(index) {
});
}
Now console.log should print PlayList function (your class). So "this" in each scope have reference to dom elements but this in Playlist.prototype.display scope have reference to Playlist function.
Solution is:
Playlist.prototype.display = function(e)
{
var self = this;
$('.episodeList').each(function(index) {
console.log(self)
console.log(this)
});
}
You need take "this" from Playlist scope and attribute to self var, so now self have refenrece to Playlist. Now you do each, so current this in each have reference to dom element but self variable still have reference to Playlist.
In your code $(this)=episodes[index] because it's in the each function. I think this is what you want,
Playlist.prototype.display = function() {
var element=$(this);
$('.episodeList').each(function(index,item) {
item.children('title').text(element.episodes[index].title);
});
}
A common practice in Javascript is to make a new variable for storing the current class, since the content of the this variable changes with context. Consider something like
function Playlist()
{
var self = this;
this.episodes = [/*episode list*/];
this.display = function()
{
$('.episodeList').each(function(index) {
$(this).children('title').text(self.episodes[index].title);
});
}
};
for your Playlist class definition, and call myPlaylist.display()
to display the content.
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I need to bind a Blur event into a Method with JS, and retrieve the object data. That's what I got:
class TestClass {
constructor(input) {
this.inputTest = input;
this.objectTest = {
1: "one",
2: "two",
3: "three"
}
this.isBinded = false;
}
test() {
if(!this.isBinded) {
this.inputTest.addEventListener("blur", function( event ) {
alert("Test Event");
// I need to access to Object Scope, but seems not to be working
console.log(this.objectTest);
});
}
this.isBinded = true;
}
}
var test = new TestClass(document.querySelector("input"));
test.test();
So, this is a simple example of what I need. I have one input, and when I initialize the class, I bind a blur event. When I try it, it just shows me the alert, so apparently looks to work.
However, it seems it cannot access into the object scope, because it doesn't return me the this.objectTest object example from the object scope.
Can anyone help me? Thanks
Because you're using a regular function in the addEventListener it is rebinding this to the inputTest element. You need to use an arrow function to keep this as your class object. Like this:
this.inputTest.addEventListener("blur", ( event ) => {
alert("Test Event");
// I need to access to Object Scope, but seems not to be working
console.log(this.objectTest);
});
However, it seems it cannot access into the object scope, because it doesn't return me the this.objectTest object example from the object scope
Yes, indeed inside the addEventListener callback, this refers to the input that you are attaching the event to, so this.objectTest will be undefined, as it's not referring your class's objectTest property.
What you need to do is to make a reference to your class this, so you can access it inside the callback, you can assign it to another variable like this:
test() {
var _self = this;
if(!this.isBinded) {
this.inputTest.addEventListener("blur", function( event ) {
alert("Test Event");
// I need to access to Object Scope, but seems not to be working
console.log(_self.objectTest);
});
}
this.isBinded = true;
}
Demo:
Here's a Demo showing how it works.
class TestClass {
constructor(input) {
this.inputTest = input;
this.objectTest = {
1: "one",
2: "two",
3: "three"
}
this.isBinded = false;
}
test() {
var _self = this;
if (!this.isBinded) {
this.inputTest.addEventListener("blur", function(event) {
alert("Test Event");
// I need to access to Object Scope, but seems not to be working
console.log(_self.objectTest);
});
}
this.isBinded = true;
}
}
var test = new TestClass(document.getElementById("js-test"));
test.test();
Check it : <input id="js-test" />
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I have this method of a JavaScript class that I've created:
resetRule() {
let sheetRules = Array.from(this.sheet.rules);
sheetRules.forEach(function(node, i) {
if(node.name != undefined) {
newRule.sheet.deleteRule(i);
}
});
}
when you instantiate a class, it essentially has to be set to a variable, like so:
const newRule = new NewRule(*params*);
and the methods/properties of said class can refer to the class object using this. like so:
this.method();
this.property;
What I'd like to know is: how does one refer back to the variable that instantiated the class within a function that is called by a method of said class?
To be even clearer: a function that is called within a method of a class alters the scope, which also means it alters the definition of this.. My question is: how do you get around this? How could you access the variable that instantiated the class when you are out the of scope of the methods within said class?
As I was composing this question, I realized that you can set the this value for a .forEach loop like this:
resetRule() {
let sheetRules = Array.from(this.sheet.rules);
sheetRules.forEach(function(node, i) {
if(node.name != undefined) {
this.sheet.deleteRule(i);
}
}, this);
}
However, the way this code works is something that--as far as I know--is just a benefit of the .forEach method, and I'd still like to know how it should be handled in general.
Hopefully this should help you out, using your example.
class Rule {
constructor(rules) {
this.sheet = {
rules: rules || []
}
}
log(){
console.log('rules:',this.sheet.rules)
}
resetRule() {
let sheetRules = Array.from(this.sheet.rules);
let self = this; // <-- here you can capture the instance
sheetRules.forEach(function(node, i) {
self.log() // <-- here you can use it in forEach
if (node.name != undefined)
this.sheet.deleteRule(i);
});
}
}
const fooRule = new Rule(['foo'])
const barRule = new Rule(['bar'])
fooRule.resetRule()
barRule.resetRule()
fooRule.log()
barRule.log()
Your forEach works because as you discovered, you passed this as an argument for the thisArg parameter. However, if you didn't, you could have just as easily set it to a variable in the outer scope and used it in the block scope.
Generally creating a variable called self or that and setting it to this is helpful, especially for arrow functions, which set this to the encapsulating scope and not the instance object.
You could make a temporary variable called self or something which would allow you to use both the object containing "this" instance as well as within that anonymous function passed to forEach, this which will refer to sheetRules when you don't specify another variable to use as this
resetRule() {
let sheetRules = Array.from(this.sheet.rules);
let self = this;
sheetRules.forEach(function(node, i) {
if(node.name != undefined) {
self.sheet.deleteRule(i);
}
});
}
If I've not misunderstood you're looking for a way to retain your scope? You have a few options here.
The immediate answers would be to use Function.prototype.bind() or Function.prototype.call() to specify the context of this when invoking those methods.
Alternatively you could just make the scope of your this available where needed:
var MyClass = function () {
// Here we bind the local scope to a variable that will give us context where necessary.
// While it's not needed here, it can give context and set a pattern of reability through repitition.
var vm = this;
vm.methodA = function () {
// We continue to set our 'vm' pointer variable when needed.
var vm = this;
globalMethod.then(function () {
// We're able to retain context of our `this` through having scope of our 'vm' variable.
vm.methodB();
});
};
vm.methodB = function () {
console.log('I did stuff!');
};
};
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
As in, sometimes when I look at code by other people, they will go var self = this; or in jquery for example, go var $self = $(this);
is there a particular reason for doing so?
It preserves the value of this for use in functions defined inside the current function.
// Contrived example
var myObject = {
func: function () {
var self = this;
setTimeout(bar, 1000);
function bar () {
alert(this); // `window`
alert(self); // `myObject`
}
}
};
myObject.func();
By holding a reference to this in some context, you have the ability to access it in other contexts such as within member functions or forEach loops.
Consider the following example:
function ViewModel() {
var self = this;
self.linksArray = ["link1", "link2", "link3"];
self.linksArray.forEach(function(link) {
// this refers to the DOM window
// and self refers to the parent context (ViewModel)
});
};
As others have mentioned, you could set a variable to $(this) if you wish to use it in another function.
On practical example would be when doing an ajax call tied to an event on the page. Using JQuery:
<script>
$(document).on("click", ".mySelector", function () {
// Where we are in the click event, $(this) refers to whatever
// element has a class of mySelector that was clicked
var self = $(this);
theDiv.html('');
$.ajax({
cache: false,
type: "GET",
url: "/SomeAjaxMethod",
data: { },
success: function (data) {
// Trying to access $(this) here will return undefined, as
// we are technically in the callback method
// Where our event is based on a class, there is likely more
// than one element on the page with the class, so it would be
// difficult to get the exact element again without some other code
self.html(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert("Ajax failed.")
}
}); // end ajax call
}); // end on mySelector class click
</script>
or:
<script>
$(document).ready(function () {
$('.foo').click(function () {
var self = $(this); // Whatever element that was clicked with foo class
$('.bar').each(function () {
var bar = $(this); // Current iteration of bar element in the loop
var baz = self; // self is still the initial value, but $(this) is not
}); // end bar loop
}); // end foo click
}); // end doc ready
</script>
The particular example (not using JQuery) is the function closure. Referencing this in a function closure refers to the function object, not the context in which the closure was defined. Your example is one way to deal with the closure problem:
var that = this;
function(){
that.something = 1;
}();
Another way to deal with this is with the apply method on the function:
function(arg){
this.something = 1;
}.apply(this, argumentArray);
The first argument in apply is the "this argument" that "this" will refer too.
One purpose of that would be to make this accessible to inner functions. for example:
function clickHandler(){
console.log(this); // this is body
var $self = this;
function inner(){
console.log(this); // this is window
console.log($self); // this is body
}
inner();
}
$("body").click(clickHandler);
Run it in console to get a sense.
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
I am trying to call a function via this reference inside of jquery scope:
var Person = function(){
this.hello = function(){
console.log("hello!");
}
this.jump = function(){
$('.jump').on('click', function(){
this.hello();
});
}
}
Then I do:
var p = new Person();
When I click over the .jump element, the console prints an error describing that hello is not a function. I am not sure what is happening here, I am assumming that this is trying to call a function inside of jquery (not sure about it).
So, googling a little bit I found the Jquery.proxy() function that could be helpfull in my situation, but every time I try to understand it my head want to explote.
Use $.proxy() like so:
var Person = function(){
this.hello = function(){
console.log("hello!");
}
this.jump = function(){
$('.jump').on(
'click',
$.proxy(
function() {
this.hello();
},
this
)
);
}
}
Passing this as the 2nd argument to $.proxy() sends that context as the value of this inside the function defined in the first argument.
Try this,
var self = this;
this.jump = function(){
$('.jump').on('click', function(){
self.hello();
});
}
when you refer to "this" inside onclick, by default this refers to the DOM element found in the value of event.target
$('.jump').on('click', function(event) {
this.hello() /// <<-- this == event.target =~ $('.jump')
}
so, fortunately, you can use a closure
var self = this;
this.jump = function(){
$('.jump').on('click', function(){
self.hello();
});
}
After looking through a few different questions regarding this topic, I'm still stumped as to how to access another function from within an object.
window.Think = {
initialize: function(){
this.currentNumber = 0;
},
updateNumber: function(){
this.currentNumber += 1;
},
listener: function(){
document.getElementById('foo').addEventListener('click', function(){
this.parent.updateNumber(); //this is where I want to call the prev function
}
}
The error I'm getting is Cannot call method 'updateNumber' of undefined
How can I call Think.updateNumber() from within listener()?
Callback functions often lose context (context is the value of this). So you have to save the value of this. to a local variable that is shared with the callback function. A common convention for this is var self = this.
listener: function(){
var self = this;
document.getElementById('foo').addEventListener('click', function(){
self.updateNumber();
}
}
this will be rebound to the function's scope. The solution is creating another variable you can refer this to:
listener: function(){
var that = this;
document.getElementById('foo').addEventListener('click', function(){
that.updateNumber();
});
}
Depending on what browsers you are targeting bind might also be a solution:
listener: function(){
document.getElementById('foo').addEventListener('click', function(){
this.updateNumber();
}.bind(this));
}
The problem is that what the keyword "this" represent.
listener: function(){//We call this is function one.
document.getElementById('foo').addEventListener('click', function(){//function two
this.parent.updateNumber(); //this is where I want to call the prev function
}
In function one,"this" represents the object Think.In function two,"this" represents the element foo.So,if you want to call the method updateNumber,you should get the reference to the object Think.We just save the "this" of function one in a variable ,like this:
listener: function(){//We call this is function one.
var outerThis=this;//save Think here.
document.getElementById('foo').addEventListener('click', function(){//function two
outerThis.updateNumber();//use Think.updateNumber here.
}
Now we get the work done. Because in javascript,the function can access it's outer function's variable,so we can use outerThis in function two.