how to work with setInterval and constructor's method.
console.log is showing undefined. Can anyone explain why and how to access the variable of constructor from setInterval.
var aa=new test();
var bb;
window.onload= function(){
bb=setInterval(aa.b,1000);
}
function test(){
this.a=1;
this.b=function (){
console.log(this.a);
}
}
Try wrapping it in a function like this:
setInterval(() => aa.b(), 1000);
The reason your way doesn't work is that you pass the b function to the setInterval, but then it lose it's this reference, so this becomes the global window object, and window.a is undefined.
Wrapping it in a function make the this be aa as you invoking the function on the aa object.
If you don't want to wrap your function in another function, you can also use bind:
setInterval(aa.b.bind(aa), 1000);
Here the this is forced to be aa.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
setInterval(aa.b.bind(aa),1000);
The others are correct - the this refers not to test instance anymore, an easier way to fix (correctly) this is using a new variable:
var aa=new test();
var bb;
window.onload= function(){
bb=setInterval(aa.b,1000);
}
function test(){
var self = this; //keep the right 'this'.
this.a=1;
this.b=function (){
console.log(self.a); //changed, `self` instead of `this`
}
}
Related
Here is my code:
$(function(){
function myfunc(){
alert("executed");
}
var function_name = "myfunc";
window[function_name]();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
As you can see, that function is not defined. Why? And how can I make it working?
The function is not defined in the global scope so it’s not a member of the window object.
You can attach the function to the window object like this.
$(function(){
window.myfunc = function(){
alert("executed");
};
var function_name = "myfunc";
window[function_name]();
})
It works only for global functions, because the scope is identically with the window object.
You could assing a function to a wanted property of the window object, just as to any other object.
function myfunc(){
alert("executed");
}
$(function(){
var function_name = "myfunc";
window[function_name]();
window.foo = _ => console.log('foo');
window.foo();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
While the direct answer to your question is that your function wasn't defined as a Global and so, attempting to call it as a property of window fails, putting your function into Global scope is not really a good answer.
Instead, make the function a method of a user-defined object (that can be put into any scope you like) and call the function as a property of that object:
// Immediately-Invoked Function Expression (IIFE)
// that keeps all of its contents out of the Global scope
(function(){
let functionHolder = {
someFunction : function(){ console.log("You did it!"); }
};
// Set up a variable that has the same name as the function
let funcName = "someFunction";
// Call the function via the object
functionHolder[funcName]();
})()
Suppose I have a function a:
function a() {
this.b = 1;
this.set = setInterval(function() {console.log(this.b);}, 200);
}
So when a.set() is called the anonymous function will be called. But this won't work as this at that time when the function is triggered points to the window object. Also it's not a good idea to use a.b as there may be multiple instances of a.
What is a good solution to this problem?
Store a reference to this:
function a() {
var self = this;
self.b = 1;
self.set = setInterval(function() {console.log(self.b);}, 200);
}
The anonymous function that you pass to setInterval has access to any variables in its containing scope, i.e., any local variables of function a(). The magic of JS closures keeps these variables alive even after a() has completed, and each invocation of a() gets its own closure.
Since we have ES6 now, I think we need another answer here:
Use an arrow function:
function a() {
this.b = 1;
this.set = setInterval(() => {console.log(this.b);}, 200);
}
Arrow functions, opposite to normal functions, don't have a this context on their own. This means you have access to the outer this.
This would be the cleanest solution, since most of the time you actually want to switch the this context for your consecutive method calls:
// store scope reference for our delegating method
var that = this;
setInterval(function() {
// this would be changed here because of method scope,
// but we still have a reference to that
OURMETHODNAME.call(that);
}, 200);
Just save your this reference in some other variable, that is not overridden by the window-call later on. Later you can use that variable to reference he object you started with.
function a() {
this.b = 1;
var that = this;
this.set = setInterval(function() {console.log(that.b);}, 200);
}
In your case, you can simply:
function a() {
var _this = this;
this.b = 1;
this.set = setInterval(function () {
console.log(_this.b);
}, 200);
}
Normally, we can also have a helper method Function.prototype.bind to fix the this reference.
This question is waay too old, but I did not like the solutions in here as the idea has mostly been about attaching the instance to something public.
Here is another, working idea:
The problem is that when calling as a callback from an interval, the scope is not inside this. However, you can kinda force it to be by defining a Function variable.
function a() {
var localCallback: () => {
// access `this` as you will
console.log(this);
};
this.timer = setInterval( localCallback, this.saveInterval );
}
Hope this is helpful!
I was playing around with javascript objects to understand "this" and function context better. I stumbled across this problem. I get the error "obj2 is not defined" unless I run window.obj2() after assigning it, but I don't know why. Shouldn't it be enough to assign the function to window.obj2 without also executing it immediately afterwards? I know that you're not supposed to pollute the window object, this is just a test.
Thanks!
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
window.obj2(); // problem when this line is commented out
(function () {
var parent = {
obj : function(){
//console.log(this);
obj2();
this.obj2();
window.obj2();
},
obj2 :function(){
console.log('obj2 in parent',this);
}
}
parent.obj();
}());
EXPLANATION
OP asks why does he have to execute the function after defining it in order for it to become defined later in the code... See what happens when you comment out the problem line.
Solution to the mystery:
You forgot a semicolon:
window.obj2 = function(){
console.log('obj2 in window.object',this);
}; // <--
Without it, the code will be interpreted as
// I'm naming the functions to refer to them later
window.obj2 = function a(){
...
}(function b() { ... }());
I.e. the parenthesis around b are interpreted as call operation of a (just like you did with b itself: (function b() {...}()).
The engine first executes b in order to pass the return value as argument to a, and only after that the return value is assigned to window.obj2.
So, at the moment b is called, window.obj2 does indeed not exist yet.
So, the reason why adding window.obj2() makes it work is not because you are accessing window.obj2, but because it makes the code un-ambigious. The following parenthesis cannot be interpreted as call operation anymore. You could use any statement there, e.g.
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
"foo";
(function () {
obj2();
}());
If you defined function window.obj2 inside the anonymous function which does call itself then it works fine, have a look code.
<script>
//window.obj2(); // problem
(function (window) {
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
var parent = {
obj : function(){
//console.log(this);
obj2();
this.obj2();
window.obj2();
},
obj2 :function(){
console.log('obj2 in parent',this);
}
}
parent.obj();
}(window));
</script>
<body>
</body>
I have tried folllowing two ways of referring a function:
First
let a = function() {
somefunction();
}
Second
let a = somefunction;
Where somefunction is the following in both cases:
function somefunction() {
alert("hello");
}
Is there any difference between these two ways?
Yes, there is a difference between your two examples.
In the first case, you are defining a new anonymous (unnamed) function which calls somefunction. You are then assigning your new function definition to the variable a. a holds a reference to your new function.
In the second case, you are simply assigning your original function of somefunction to the variable a. The variable a then holds a reference to somefunction. You are not creating a new function as you are in the first case.
I think this example may make the difference clear. arguments is an array like object that contains each of the arguments passed to a function.
Try running each of these lines on your favorite browser console.
var somefunction = function() { console.log(arguments); };
Your first example demonstrates defining a named function a that closes around the named function somefunction.
var a = function() { somefunction(); };
Your second example makes a reference, b, directly to somefunction. This makes invoking b the same as invoking somefunction.
var b = somefunction;
Now if you call each of these a and b with some arguments you will see the difference.
=> a('a', 1);
[]
=> b('a', 1);
['a', 1]
In the first case the arguments object is empty. That's because the arguments that were passed to a were not forwarded onto somefunction.
In the second case the arguments are available to somefunction, because some function is being called directly.
Here is how you could redefine a so that it were functionally equivalent using apply
var a = function() { somefunction.apply(this, arguments); }
Running this at your console prints the argument array.
=> a('a', 1);
['a', 1]
var a = function(){
somefunction();
}
Is an Anonymous Function attributed to a variable.
somefunction :function() {
alert("hello");
}
Is an declaration of a function throungh the Object Literal notation.
The diference are shown when you are creating an object. The anonymous function are not acessible as a "public" method, instead in the Object Literal notation, that are acessible from outside.
As Douglas Crockford said, in JS the Good Parts, the first declaration are just a function and the second one could be a method.
In the first case, you are creating a function which calls someFunction(), then you assign that function to a, so now calling a() calls an anonymous function which in turn calls someFunction().
In the second case, a and someFunction become the exact same thing, calling a() is the same as calling someFunction().
The way you're setting var a by accessing the function is clearly out of scope.
So I suspect you have a typo : instead of = :
var somefunction = function() {
alert("hello");
};
somefunction(); // hello
...Now that your first and second makes sense with the code above:
Anonymous Function stored in variable:
var a = function(){
alert('Hey');
somefunction();
};
a(); // Hey // hello
Variable as Function Reference
var a = somefunction;
a(); // hello
In the other case than:
var objLiteral = {
somefunction : function() {
alert("hello");
}
};
var a = objLiteral.somefunction;
a(); // hello
This is what i am facing with
function AAA(){
this.f1 = function (){
/*expecting that f2 will be call as both of then are of same object.*/
console.log(f2(5));//
}
this.f2 = function(x){
return x;
}
}
x = new AAA();
x.f1(); //ReferenceError: f2 is not defined
Neither does it work,
function AAA(){
this.f1 = function (){
/*expecting that f2 will be call as both of then are of same object.*/
console.log(f3(5));//
}
/*naming the function f3 hope to get function reference, as function
on the right side has name now and in the closure of f1, right?*/
this.f2 = function f3(x){
return x;
}
function f4() {};
}
x = new AAA();
x.f1(); //ReferenceError: f3 is not defined
What is happening here? who are in closure of 'f1' except 'f4'? can't we call the same object function without 'this'?
You are not really using closures here. It will work fine if you change the line to
console.log(this.f2(5));
If you want to use closures, you can rewrite the class as follows:
function AAA()
{
var f1 = function()
{
console.log(f2(5));
};
// f2 is a private function.
var f2 = function(x)
{
return x;
};
// Define the public interface.
return { f1: f1 };
}
You’re confusing a few things here; this and closures are two completely different issues.
Your problem here is that you’re trying to refer to f2 directly, thereby assuming that this is part of the current execution scope. It isn't.
If you put f2 on this, you’ll have to keep referencing it as this.f2. To be able to reference f2 directly, you’ll have to declare a (separate) variable by that name, which you can then assign to this if you want, as qwertymk says.
Personally, I try to avoid this as much as I can, since its meaning is completely dependent on how the function is called (e.g. if AAA is called without specifying the new operator, this will refer to the global object!). It also saves you from headaches like the one above. Closures (as demonstrated by Elian) are a much better way of obtaining this functionality.
Interestingly enough, I've found I hardly ever need to use this.
In Elian's example, f2 is closed over: once the AAA function is done running, nobody can access f2, except the functions that were defined inside AAA (and are still accessible). In this case, the function f1 is accessible from the returned object, so that still exists. Therefore, f1 can still use f2.
That's what closures are about: a function can still access all the variables in its scope, even when those variables were declared in a function that's terminated.
It should be this.f2() not f2() by itself. You would use f2() if it was a private variable which means if it was created with a var keyword.
function AAA(){
var f3 = function(x) { return x; };
this.f1 = function (){
/*expecting that f2 will be call as both of then are of same object.*/
console.log(this.f2(5));//
console.log(f3(10));
}
this.f2 = function(x){
return x;
}
}
DEMO
Others have already told you what the problem is, so i will not repeat it. If you want your code to work, you just need a reference to this:
function AAA(){
var self = this;
this.f1 = function (){
console.log(self.f2(5)); //self.f2 exists, yay
}
this.f2 = function(x){
return x;
}
}
x = new AAA();
x.f1(); //5