Javascript closure (this)
Arrow function set this
to the lexical scope. You're trying to access the scyla
object but the arrow function is setting it to window
(or whatever this
is equal to at the time that you declare scyla
).
Either reference scyla
directly:
scyla.rsGame();
or write your methods using standard function expressions:
update: function() {
...
if (this.player.inWorld === false)
this.rsGame();
}
or shorthand method declarations:
update() {
...
if (this.player.inWorld === false)
this.rsGame();
}
JavaScript closure and the this object
As soon as you call:
return func(par);
You're creating a new scope (with its own this
) and in this case because you haven't specified an object, this === window
usually or undefined in strict mode. The called function does not inherit whatever this
was in the calling scope.
Ways to set a value for this are:
myobj.func(par); // this === myobj
or
func.call(myobj, ...) // this === myobj
There are also:
- apply
- bind
- arrow functions, where this is set to the same value as the outer execution context (also see MDN:Arrow functions )
this keyword inside closure
t
is just a normal variable in the scope of the outside anonymous function (and thus also the inner anonymous function). It isn't a property on an object, so you simply set it without reference to this
, that
, or the_other
.
var test = (function(){
var t = "test";
return {
alertT: function(){
alert(t);
},
setT: function (new_value) {
t = new_value;
}
}
}());
test.alertT();
test.setT('hello, world');
test.alertT();
The syntax you are using is the usual pattern for creating something that acts like a private variable in JS.
javascript closures and local variable 'remembering'
It's because in the second example, you're calling a
a second time, while in the first one a
is only called once. Each time you call a
, the value of x
is initialised as 5. It is the inner function which is returned which creates the closure, and the value of x
is remembered between invocations of that function. But each time you return a new function from a
, it initially has access to an x
which holds the value 5.
JavaScript closure inside loops – simple practical example
Well, the problem is that the variable i
, within each of your anonymous functions, is bound to the same variable outside of the function.
ES6 solution: let
ECMAScript 6 (ES6) introduces new let
and const
keywords that are scoped differently than var
-based variables. For example, in a loop with a let
-based index, each iteration through the loop will have a new variable i
with loop scope, so your code would work as you expect. There are many resources, but I'd recommend 2ality's block-scoping post as a great source of information.
for (let i = 0; i < 3; i++) {
funcs[i] = function() {
console.log("My value: " + i);
};
}
Beware, though, that IE9-IE11 and Edge prior to Edge 14 support let
but get the above wrong (they don't create a new i
each time, so all the functions above would log 3 like they would if we used var
). Edge 14 finally gets it right.
ES5.1 solution: forEach
With the relatively widespread availability of the Array.prototype.forEach
function (in 2015), it's worth noting that in those situations involving iteration primarily over an array of values, .forEach()
provides a clean, natural way to get a distinct closure for every iteration. That is, assuming you've got some sort of array containing values (DOM references, objects, whatever), and the problem arises of setting up callbacks specific to each element, you can do this:
var someArray = [ /* whatever */ ];
// ...
someArray.forEach(function(arrayElement) {
// ... code code code for this one element
someAsynchronousFunction(arrayElement, function() {
arrayElement.doSomething();
});
});
The idea is that each invocation of the callback function used with the .forEach
loop will be its own closure. The parameter passed in to that handler is the array element specific to that particular step of the iteration. If it's used in an asynchronous callback, it won't collide with any of the other callbacks established at other steps of the iteration.
If you happen to be working in jQuery, the $.each()
function gives you a similar capability.
Classic solution: Closures
What you want to do is bind the variable within each function to a separate, unchanging value outside of the function:
var funcs = [];
function createfunc(i) {
return function() {
console.log("My value: " + i);
};
}
for (var i = 0; i < 3; i++) {
funcs[i] = createfunc(i);
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
Javascript closures with two instantiation
As others have mentioned, you've basically created two closures.
The easiest way to understand closures is that it is a generalisation of the concept of global variables. In fact, global variables in javascript is nothing more than a closure in global scope.
A closure is the mechanism by which the body of a function may reference variables in outer scope. As I said above, global variables are nothing more than a closure:
var x;
function x_plus_plus () {
x++; // this variable is captured by a closure
}
Every scope allows you to create a closure. So apart from the global scope you can also create a closure inside other functions. To me, personally, the minimum example code that best illustrates what closures are is an IIFE that defines two functions that share a variable:
var incr;
var val;
(function(){
var x = 0; // shared with the functions below var via closure
incr = function(){x++};
val = function(){return x};
})();
incr();
incr();
console.log(val()); // outputs 2 because the functions share x
console.log(x); // syntax error - x does not exist in this scope
Note that a closure is what happens between a variable and functions declared in that variable's scope. It is not what happens between a variable and the function the variable is declare in:
function () { <─────┐
├── this is not a closure
var foo; <───────┘
}
function () {
var foo; <────────────────┐
├── this is a closure
function bar () { │
do_something(foo); <───┘
}
}
var x; <───────────────┐
├── this is also a closure but we
function y () { │ normally call it "global variable"
do_something(x); <───┘
}
Side note: Global variables in js are actually a bit unique because they're also properties of the global (window) object. But in theory they behave as if they're an instance of a closure. The point is that thinking of closures as a global-variable-like mechanism is the easiest way to understand them.
Related Topics
How to Create Every Combination Possible for the Contents of Two Arrays
How to Concatenate Properties from Multiple JavaScript Objects
Create Array of Unique Objects by Property
Ecmascript 6 Features Available in Node.Js 0.12
How to Use Any HTML5 Fanciness to Export Local Storage to Excel
Counting and Limiting Words in a Textarea
Best Way to Execute Js Only on Specific Page
Screen Scraping from a Web Page with a Lot of JavaScript
Style.Display='None' Doesn't Work on Option Tags in Chrome, But It Does in Firefox
How to Get the Index of an Object by Its Property in JavaScript
Url Encode a String in Jquery for an Ajax Request
Rails 4 Turbo-Link Prevents Jquery Scripts from Working
Http Get Request in Node.Js Express
How to Create a Responsive Image That Also Scales Up in Bootstrap 3