This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
i'm trying build slideshow function with OOP literal way.
so, this is my code :
"use strict";
var slideshow = {
elSet : $(".slideshow"),
elCount : indexCount(".dealList"),
elWidth : width(".dealList"),
elNo : 1,
next : function() {
if (this.elNo < this.elCount) {
console.log(this.elSet);
this.elNo += 1;
this.elSet.style.transform = "translateX(-" + this.elWidth * this.elNo + "px)";
}
else {
console.log(this.elSet);
this.elNo = 1;
this.elSet.style.transform = "translateX(-" + this.elWidth * this.elNo + "px)";
}
},
initial : function() {
var loop = setInterval(this.next, 5000);
}
}
slideshow.initial();
the problem occure in browser console :
out of memory
console.log return undefined
it is possible the problem occure because of this keyword?
what's wrong with my code?
The callback of the setInterval() when executed is bound to the global object and not your object. You can, however, bind it to your object by using this code instead:
initial : function() {
var loop = setInterval(this.next.bind( this ), 5000);
}
MDN on bind()
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 4 years ago.
I am trying to understand the bind method and I have written the below code :
//
//Window Context
function Hello(d) {
//Always this reffers to calling context
console.log(d);
}
Hello("ABC");
function Student(sname) {
this.name_n = sname;
this.hello = Hello;
this.printAfter2Seconds = printAfter2Seconds.bind(this);
this.print = function() {
console.log(`Student Name: ${this.name_n}`);
}
}
printAfter2Seconds = function() {
console.log(`Before Set TimeOut - ${this.name_n}`);
//let that = this;
setTimeout(function() {
//console.log(this);
console.log(`After Set TimeOut - ${this.name_n}`);
},2000);
}
function Department(dname) {
this.name_n = dname;
this.hello = Hello;
this.printAfter2Seconds = printAfter2Seconds.bind(this);
}
let s = new Student("ABC");
s.hello(s.name_n);
s.printAfter2Seconds();
let d = new Department("IT");
d.hello(d.name);
d.printAfter2Seconds();
//
If I comment the setTimeout line and the line ending setTimeout like below :
//setTimeout(function() {
//console.log(this);
console.log(`After Set TimeOut - ${this.name_n}`);
// },2000);
I am getting the expected output ABC and IT. But If I include setTimeout I am getting undefined both time. So I am guessing some where I need to invoke bind again. This may not be a trivial example that you use everyday just trying to understand bind.
So I need to understand how to bind the this context of the function inside setTimeout or that is even possible.
Thanks in Advance.
This question already has answers here:
Given a string describing a Javascript function, convert it to a Javascript function
(8 answers)
Closed 7 years ago.
Say I have a function in javascript
var fn = function () {
return 6 + 5;
};
and then I do
fn.toString();
which returns
"function () { return 6 + 5; }"
how can I turn this back into a function and eventually call it later on. I've tried eval as other people have said but this does not seem to be working for me. Any help would be much appreciated!!!
You can give a name to the function, then you can call it. This should work
var fn = function () {
return 6 + 5;
};
var stringFunc = fn.toString();
eval("var newfn = " + stringFunc);
console.log(newfn())
you can also execute it passing the parameters like this
console.log(eval("("+stringFunc+")()"))
#LeeDennis just call fn(); instead of fn.toString(); the variable "fn" is the function you just need to add the parenthesis.
I console logged the outputs so you can see them.
//CODE
<!DOCTYPE html>
<html>
<head>
<script>
var fn = function () {
return 6 + 5;
};
console.log(fn()); //returns 11
console.log(fn.toString()); //returns "function () { return 6 + 5; }"
</script>
</head>
<body>
</body>
</html>
Use eval():
fnString = 'function () { return 6 + 5; }';
fn = eval('(' + fnString + ')');
alert(fn());
Check this out:
JavaScript eval() "syntax error" on parsing a function string
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
I have following code :
function A() {
this.value = 'a_value';
}
A.prototype.getValue = function(){
console.log(this.value); // got undefined, expected 'a_value'
}
setTimeout(new A().getValue, 100);
why i get this.value as undefined.?
and how how do i access this.value?
EDIT : i am not allowed to change the setTimeout line (last line) of code.
Hint: have you tried console.log(this);?
You are only passing the getValue function to setTimeout, not its context. Something like this would work: setTimeout(function() {new A().getValue();},100); But without changing that last line, there's basically nothing you can do.
you can avoid using the this altogether and not having this kind of problems with the following technique :
var A = function () { // no new no this
var value = 'a_value';
var getValue = function(){
console.log(value);
};
return Object.freeze({
getValue ,
});
};
setTimeout(A().getValue, 100);
or write
var a = new A();
before, and then
setTimeout(a.getValue.bind(a), 100);
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
JavaScript setInterval and `this` solution
(9 answers)
Closed 8 years ago.
EDIT: The practice below is NOT correct. The solution is to store "this" in another variable and use that in the setInterval function. See answers below.
this.growImage = function() {
console.log("growImage:" + this.dom.id + "counter:" + this.grow_counter);
if(this.grow_counter == 0) {
this.tim_grow = window.setInterval(
/******* FUNCTION TO BE CALLED BY SETINTERVAL ********/
function() {
this.grow_counter++;
console.log("this.growStepByStep(): this.grow_counter = " + this.grow_counter); /*this is displayed as NaN */
if(this.grow_counter > this.times) {
window.clearInterval(this.tim_grow);
this.grow_counter = 0;
}
}
/******* FUNCTION TO BE CALLED BY SETINTERVAL ********/
,
20);
}
}
EDIT: The above solution is NOT correct.
It does not work. The console log does not "see" this.grow_counter, and displays a NaN instead. this.grow_counter is just a numeric value.
NOTE: that this function uses this inside it, so other simpler solutions won't do either.
Thanks in advance!
The value of this is NOT preserved in your setInterval() callback. You have to save that value you want to another variable before the setInterval() call and use that inside the setInterval().
this.growImage = function() {
console.log("growImage:" + this.dom.id + "counter:" + this.grow_counter);
if(this.grow_counter == 0) {
var self = this;
this.tim_grow = window.setInterval(
/******* FUNCTION TO BE CALLED BY SETINTERVAL ********/
function() {
self.grow_counter++;
console.log("self.growStepByStep(): self.grow_counter = " + this.grow_counter); /*this is displayed as NaN */
if(self.grow_counter > this.times) {
window.clearInterval(self.tim_grow);
self.grow_counter = 0;
}
}
/******* FUNCTION TO BE CALLED BY SETINTERVAL ********/
,
20);
}
}
Or, if you are using modern browsers only, you can also use .bind() to manipulate the value of this to be set as you want like this:
this.growImage = function() {
function intervalCallback() {
this.grow_counter++;
console.log("this.growStepByStep(): this.grow_counter = " + this.grow_counter); /*this is displayed as NaN */
if(this.grow_counter > this.times) {
window.clearInterval(this.tim_grow);
this.grow_counter = 0;
}
}
console.log("growImage:" + this.dom.id + "counter:" + this.grow_counter);
if(this.grow_counter == 0) {
this.tim_grow = window.setInterval(intervalCallback.bind(this), 20);
}
}
Neit is correct, but to give a little bit more info.
You aren't understanding the scope that you are in when inside the setInterval.
Inside of your setInterval, you've created a new scope and 'this' only refers to things inside that new scope. His/her suggestion of setting a variable me = this and then using me.grow_counter means you are storing the outer scope in the variable 'me', which can then be used in your setInterval scope (although I would like to see a better variable name!).
Hope that helps.
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
I have an object containing a number of buttons (label and callback) which I dynamically want to add to the DOM:
var buttons = {
'Save': function() {
return false;
},
'Abort': function() {}
};
for(label in buttons) {
$('#buttonbar').append('<button>' + label + '</button>');
var callback = buttons[label];
$('#buttonbar button:last-child').click(function() {
//var result = callback();
alert(callback);
});
}
But regardless which button I click, the variable callback always contains the function of the last button. See this fiddle.
Any ideas how to solve that?
Thanks to the hint given by Barmar I found the solution:
var buttons = {
'Save': function() {
return false;
},
'Abort': function() {}
};
for(label in buttons) {
$('#buttonbar').append('<button>' + label + '</button>');
var callback = buttons[label];
(function(cb) {
$('#buttonbar button:last-child').click(function() {
alert(cb);
});
})(callback);
}