Why object property became undefined when using setInterval - javascript

As below code, I make an object named "test", and give it properties and method.
The property came from its argument.
And I try to call the method every 2 sec after onload, and the result shows undefined.
But if I only call the method not using setInterval(), like this
window.onload = function() {
giveword.showWord();
}
I'll be able to show the text "Hi".. Why is that?
var giveword = new test("Hi");
function test(word) {
this.word = word;
}
test.prototype.showWord = function() {
document.getElementById("msg_box").innerHTML = this.word;
}
window.onload = function() {
setInterval(giveword.showWord, 2000);
}
Thanks for help...

The reason is because in your test.prototype.showWord function your this object is referring to the context in which the function is called, which is the window object when called from setInterval.
I think what you want to do is use a closure to make the context of showWord() be the giveword instance like this:
var giveword = new test("Hi");
function test(word) {
this.word = word;
}
test.prototype.showWord = function() {
document.getElementById("msg_box").innerHTML = this.word;
}
window.onload = function(){
setInterval(function(){giveword.showWord();}, 2000); // <<-- here's the closure
}
The difference is that with the closure you're telling the setInterval function to call a function within the context as it was when the setInterval was declared. When setInterval was declared there was a variable in scope called giveword that had a method showWord() that returns the value of your initial input. (Closures are hard to explain, and I'm afraid you'd be best served by someone else explaining them if you need more info.)

This solution this now so easy, use an arrow function in setInterval. Here is an example using setInterval inside of an object method.
const mobile = {
make: 'iPhone',
model: 'X',
battery: 10,
charging: false,
charge: function() {
if(this.battery < 100) {
this.charging = true;
console.info('Battery is charging...');
let interval = setInterval(() => {
this.battery = this.battery + 10;
console.info(mobile.battery);
if( this.battery === 100){
this.charging = false;
clearInterval(interval);
console.info('Battery has finished charging.');
}
}, 100);
}
else {
console.info('Battery does not need charging.');
}
}
}

Related

How can I increment the value of a parameter in an object using a function?

I want to be able to increment/change the value of a parameter inside an object. I want the value to change by accessing the value of a variable that is incrementing inside another function.
The example code below shows what I am trying to do. I would like options.number to increase as i inside masterLoop increases.
I know that i isn't defined in the scope of function calc(), but I can't think of a way to retrieve the value of i while maintaining this general code structure.
(function masterLoop(i) {
setTimeout(function() {
++i;
masterLoopStage = i;
console.log('Stage is: ' + i);
masterLoop(i);
}, 5000)
})(1);
function calc() {
number = i; // I know i isn't defined in this scope, but I can't figure out how access the incrementing value of i inside this function
return number;
}
var options = {
number: calc() // I want this vale to increase along with i inside masterLoop()
};
setInterval(function() {
console.log(options.number);
}, 5000);
Typically, in cases like this, I would try to use a return to retrieve a value, but I wasn't able to find a solution with that either since the incrementing value is inside a setInterval and thus its scope isn't available to the return.
Here is an example of that:
function calc() {
var foo = 1;
setInterval(function() {
var foo = foo + 1;
}, 1000);
return foo; // the incrementing value of foo is not available outside the scope of setIterval, so this won't work. The return also won't work inside setInterval.
}
var optionsConstant = {
maxVolume: 10
};
var options = {
maxVolume: optionsConstant.maxVolume + calc() // I want calc() to be able to increment along with foo in the setInterval above.
};
setInterval(function() {
var maxVolume = options.maxVolume;
console.log('maxVolume: ' + maxVolume);
}, 5000);
Taking your second attempt, you could make calc an immediately invoked function expression -- providing a closure -- and in it return a function that has access to foo.
Then, to keep the final syntax of options.maxVolume, you should define that property as a getter, so that in fact it will execute some code when accessed, calling calc():
var calc = (function () { // create closure for foo
var foo = 1;
setInterval(function() {
foo = foo + 1; // remove var!
}, 100);
return function calc() { // return a function
return foo;
}
})();
var optionsConstant = {
maxVolume: 10
};
var options = {
get maxVolume() { // make it a getter
return optionsConstant.maxVolume + calc();
}
};
setInterval(function() {
var maxVolume = options.maxVolume;
console.log('maxVolume: ' + maxVolume);
}, 500);
Can you declare the increment variable outside the masterloop function scope so the other functions can access it and read its' value when needed?
You'll need to make sure to re-initialize it's value when appropriate.
I think you need to use a closure. Here's one example:
let returnI = (function masterLoop(i) {
setTimeout(function() {
++i;
masterLoopStage = i;
console.log('Stage is: ' + i);
return masterLoop(i);
}, 5000)
})(1);
function calc() {
number = returnI;
return number;
}
var options = {
number: calc()
};
setInterval(function() {
console.log(options.number);
}, 5000);

Call a returned function from outside its function

I'm trying to call a function that's returned from a function. Here's what I mean:
myFunction.something; // (Wrong)
function myFunction() {
return {
something: function() {
...
}
};
}
When I try calling myFunction.something nothing happens. How can I call a returned function outside of its function?
JSFiddle
var index = 0;
var animID = requestAnimationFrame(myFunction.something);
function myFunction() {
return {
something: function() {
index++;
console.log(index);
if (index === 5) cancelAnimationFrame(animID);
else animID = requestAnimationFrame(myFunction.something);
}
};
}
I would first of all recommend using descriptive variable names; utils rather than myFunction, and incrementFrame rather than something, for example. I would second of all recommend reconsidering your approach to code organization and simply putting all of your helper functions directly in an object, then referencing that object:
var index = 0;
var animID = requestAnimationFrame(utils.incrementFrame);
var utils = {
incrementFrame: function() {
index++;
console.log(index);
if (index === 5) cancelAnimationFrame(animID);
else animID = requestAnimationFrame(utils.incrementFrame);
}
}
There are a few differences between these approaches, some of them frustratingly subtle. The primary reason I recommend using an object for organization rather than a function which returns an object is because you don't need to use a function for organization; you are unnecessarily complicating your code.
myfunction is not the object that you get from calling myfunction(), it's the function itself and does not have a .something method.
You could call it again (as in myfunction().something()), but a better approach would be to store a reference to the object you've already created:
function myFunction() {
var index = 0;
var o = {
something: function() {
index++;
console.log(index);
if (index < 5) requestAnimationFrame(o.something);
// btw you don't need to cancel anything once you reach 5, it's enough to continue not
}
};
return o;
}
myFunction().something();
Alternatively you might want to drop the function altogether, or use the module pattern (with an IIFE), as you seem to use it like a singleton anyway.
Try this:
myFunction().something()
myFunction() calls the myFunction function
them we use the dot notation on the returned value (which is an object) to find the something member of it
that member is a function too, so add another set of brackets () to call it
Call function after writing it
var index = 0;
function myFunction() {
return {
something: function() {
index++;
console.log(index);
if (index === 5) cancelAnimationFrame(animID);
else animID = requestAnimationFrame(myFunction().something);
}
};
}
var animID = requestAnimationFrame(myFunction().something);

Call function in custom function

I'm trying to figure out how this custom jQuery functions work by experimenting a bit. I can't however get it to work properly. I'm trying to call the prepareSlide function in my setInterval but it says prepareSlide is not defined
$('document').ready(function(){
jQuery('.item_holder').itemSlider({
start: 1,
carousel: true
});
});
$.fn.itemSlider = function (details) {
var currentSlideNumber = (details && details.start > 0) ? details.start : 1;
this.prepareSlide = function(slideNumber) {
alert(1)
}
//Set an interval
var itemToSlide = currentSlideNumber + 1;
slideTimer = setInterval("prepareSlide(" + itemToSlide + ")", 5000);
}
You should provide a function to the first argument of setInterval. Also, to provide the context properly to the function invocation, a quick method is to preserve this by having another variable reference it, which in this case, we call self
var self = this;
slideTimer = setInterval(function(){
self.prepareSlide(itemToSlide)
}, 5000);

asp.net ajax property value timestamp is undefined

I have a problem with the value assignment and retrieval in asp.net ajax. The value of timestamp is undefined
Code:
/// <reference name="MicrosoftAjax.js"/>
Type.registerNamespace("LabelTimeExtender1");
LabelTimeExtender1.ClientBehavior1 = function(element) {
LabelTimeExtender1.ClientBehavior1.initializeBase(this, [element]);
this._testelement=this.get_element();
this._timestamp= this.get_element().attributes['TimeStamp'].value;
alert(_timestamp);
},
LabelTimeExtender1.ClientBehavior1.prototype = {
initialize: function() {
LabelTimeExtender1.ClientBehavior1.callBaseMethod(this, 'initialize');
setInterval (this.timer,1000);
alert("after");
},
dispose: function() {
//Add custom dispose actions here
LabelTimeExtender1.ClientBehavior1.callBaseMethod(this, 'dispose');
},
timer: function(){
alert(this.timestamp);
var splitdate=this._timestamp.split(/[:]+/);
alert(splitdate);
var date= new Date(this._timestamp);
alert( date.toString());
var datenow= new Date ();
alert(datenow.toString());
this._element.innerText=" ";
alert(this._element);
if(date.getUTCFullYear<datenow.getUTCFullYear)
{
alert("year");
var myelement= this.get_element();
myelement .innerHTML= date.getUTCFullYear.toString();
}
if(date.getUTCMonth<datenow.getUTCMonth)
{
alert("month");
this.get_element().innerHTML=date.getUTCMonth.toString();
}
if(date.getUTCDay<datenow.getUTCDay)
{
this.get_element().innerHTML=date.getUTCDay.toString();
}
if(date.getUTCHours <datenow.getUTCHours )
{
this.get_element().innerHTML=date.getUTCHours .toString();
}
if(date.getUTCMinutes<datenow.getUTCMinutes)
{
this.get_element().innerHTML=date.getUTCMinutes.toString();
}
},
set_timestamp: function(value)
{
this._timestamp=value;
},
get_timestamp: function()
{
return this._timestamp;
}
}
LabelTimeExtender1.ClientBehavior1.registerClass('LabelTimeExtender1.ClientBehavior1', Sys.UI.Behavior);
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
Why is the value of _timestamp undefined?
I would suggest moving the code which sets this._timestamp into your initialize function.
My other suggestion is to use the getters and setters even within your own code to ensure encapsulation. So, the alerts would actually be alert(this.get_timestamp()). And, in your initialize function, you would call this.set_timestamp(this.get_element().attributes['TimeStamp'].value).
Thanks to the comment I see the problem is actually in the setInterval call. When you call window.setInterval(this.timer, 1000);, when the timer function is called this refers to window, not to your object. So instead, do something like this:
var self = this;
window.setInterval(function () {
self.timer();
}, 1000);
That will make this inside of timer() refer to the correct object.

onchange javascript variable

Is there a way to call a JavaScript function if a javascript variable changes values using jQuery?
Something to the extend of -
var test = 1;
test = 2; // calls a javascript function
test = 3; // calls a javascript function
This way I wouldn't have to add an onchange event to so many different functions.
(Something seems a bit carelessly planned in your code if you need functionality like that)
The easiest way to add that feature is to create a function for updating your variable, that also calls whatever other function you want to.
Instead of:
var test = 1;
test = 2; // calls a javascript function
test = 3; // calls a javascript function
You do:
var test = 1;
function set_test(newval) {
test = newval;
my_callback(); // this is whatever you wanted to call onChange
}
set_test(2);
set_test(3);
try this, it's real variable change event:
var book = {
_year: 2004,
edition: 1
};
Object.defineProperty(book, "year", {
get: function(){
return this._year;
},
set: function(newValue){
this._year=newValue;
this.edition=newValue-2004;
alert(this._year);
alert(this.edition);
}
});
book.year=2017
// will alert 2017 and 13
No, there is not, just polling with setInterval or setTimeout or callbacks. Events only apply to DOM. I'd suggest that you try to go with callbacks and do things like this:
function foo(data, callback)
{
// do things with data
callback(data);
}
function bar(data)
{
console.log('callback can has', data);
}
foo('baz', bar);
It's a rough example, but should give you the idea.
One option is to wrap your data into a heavier object.
var Watching = function(){
var a;
this.getA(){
return a;
};
this.setA(value){
a = value;
this.trigger('watch');
};
his.watchA(callback){
this.bind('watch', callback);
};
};
var obj = new Watching();
obj.watchA(function(){ alert('changed'); });
obj.setA(2);
This doesn't answer your question exactly, but it may solve your problem:
make your variable as html content of an element, then use jQuery change() event
<script>
document.write("<div id='test'>"+test+"</div>";
$("#test").change(function(){//your script here});
</script>
You can create a class to be notified when your variable changed.
this is the class:
class ListeningVariable {
constructor(val, changeHandler) {
this.val = val;
this.changeHandler = changeHandler
}
set value(val) {
if (this.val !== val) {
this.changeHandler(val);
}
this.val = val;
}
changeHandler(val) {}
}
Then you can create an instance of this class instead of your variable:
let myVar = new ListeningVariable(25/*initialize*/, function(val) {
console.log("variable Changed to:", val);
}/*handler function*/);
And when you want to change your variable, just use this code:
myVar.value = 20; // calls the changeHandler function
myVar.value = 20; // does't call the changeHandler function
myVar.value = 40; // calls the changeHandler function
You can do something like this with setting intervals to keep track of change:
var dataToChange = 1;
var key = dataToChange;
var int = setInterval(() => {
if (dataToChange != key) {
console.log('changed'); /// if data changes
clearInterval(int);
} else {
console.log('nothing changed'); /// while nothing changes
}
}, 3000);
setTimeout(() => {
///// supposedly this is when the variable changes
dataToChange = 2;
}, 9000);
The below function will poll for changes in the test variable every 5 seconds:
// initialize test variable globally
var test = 1;
// global variable to store the previous value of test
// which is updated every 5 seconds
var tmp = test;
setInterval("pollForVariableChange()", 5000);
function pollForVariableChange() {
if (tmp != test) {
alert('Value of test has changed to ' + test);
}
tmp = test;
}

Categories

Resources