Why I can't access variable in js function with "this" [duplicate] - javascript

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 8 years ago.
I am learning javascript. Have two blocks of code in below.
As you can see that first one works just fine but second one does not. Different between them is that I use this.count to access the count variable defined in the counter2,
function counter1(start){
var count = start;
var increase = function(){
count++;
};
var getValue = function(){
return count;
};
return {
inc : increase,
get :getValue }
}
var c1 = new counter1(5);
c1.inc(); //is able to increase 1
console.log(c1.ge());//can return 6
function counter2(start){
var count = start;
var increase = function(){
this.count++;
};
var getValue = function(){
return this.count;
};
return {
inc : increase ,
get :getValue }
}
var c2 = new counter2(5);
c2.inc(); //can NOT access this.count
console.log(c2.ge());//return NaN
I am a little confused with the "this" in counter2 as you can see, when I debug the code, "this" is counter2, but just has no access the the count variable
So could you help me to understand why 'this' in counter2 is not have the access to the count variable?
and why I can access count variable in the increase function in counter1 even if I did not use "this". Does this makes the code "worse" (less accessible)?
Thanks

When you call a constructor function with the "new" keyword, the context variable "this" points to itself and is implicitly returned from the end of the constructor function. When you are explicitly returning your new object inc and get functions, you are no longer returning "this" that is created with the constructor anymore. To be able to use with "this", you need to expose inc and get functions on "this" within the constructor function:
function counter2(start) {
//ensure counter2 function was called with "new" keyword
if (!(this instanceof counter2)) {
return new counter2(start);
}
this.count = start;
this.inc = function(){
this.count++;
};
this.get = function() {
return this.count;
};
//When called with "new" this is implicitly returned, your constructed object.
//return this;
}
var c2 = new counter2(5);
c2.inc();
As others have pointed out, exposing "count" inside your explicitly returned object would also allow you to access count through "this.count" since count is now a part of the object that you are returning. In this case, "this" will point to the object itself (which will need a count defined).
function counter2(start) {
var count = start;
var increase = function(){
this.count++;
};
var getValue = function() {
return this.count;
};
return {
count: count,
inc: increase,
get: getValue
}
}
var c2 = new counter2(5);
c2.inc();

So to start off I think you should learn a little about the Constructor pattern and 'Inheritance' in javascript.
Constructor Pattern
When you call new counter2(5) the counter2 function attempts to create a new object which would be called this inside the function, so you can add functions to it, which will allow you to access the state of the variables, such as count.
If you are just learning javascript then it would probably be easier for you if you try not to use var inside your counter2 and use the this keyword and have your function looking like the following:
function Counter(start) {
this.count = start;
this.increase = function () {
this.count++;
}
this.get = function () {
return this.count;
}
}
This is the basics of the Constructor pattern in Javascript.
As I have said this inside the function refers to the object being created, which only happens because you used the new keyword. This can be a complicated subject, but what this is set to inside a function can be changed, which is why im linking Function#bind as some reading.
It can be alot to take in at first, but heres some basic reading to get you started:
Reading
(Constructor Pattern)[http://www.samselikoff.com/blog/2013/11/14/some-Javascript-constructor-patterns/]
(Inheritance and the prototype chain)[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain]
(Function.prototype.bind)[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind]
Good luck!!

Related

javaScript issue about "this" [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 5 years ago.
I'm trying to build a game demon, and run into a problem when I'm trying to add a clickEventHanlder to a button, the code goes here:
function GameConstructor(){
this.start = startGame;
this.count = 5;
...
function startGame(){
if(this.count > 5){ //here goes the problem, this don't point to the game object when I click the button
...
}
}
...
var game = new GameConstructor(); //game object has a method called start
$("#someBtn").click(game.start); //in the method start this now point to the button so this.count is undefined.
I know I can define a global variable count = 5 to solve this, but I just wonder if there is a way to fix in my original way? Thanks.
I'm not a complete JavaScript wizard, but my guess is that the this inside your nested function is referring to that nested function, not the outer instance.
Many people opt to create a self variable instead, to be a bit more explicit about this scope stuff. Maybe try this:
function GameConstructor(){
var self = this; // <-- here, then reference self subsequently
self.start = startGame;
self.count = 5;
...
function startGame(){
if(self.count > 5){ //here goes the problem, this don't point to the game object when I click the button
...
}
}
this always point to the current function context in Javascript. Means the lowest function just out of the 'this'. So, you can do like;
function GameConstructor(){
var self= this;
this.start = startGame;
this.count = 5;
...
function startGame(){
if(self.count > 5){ //here goes the problem, this don't point to the game object when I click the button
...
}
}
...
var game = new GameConstructor(); //game object has a method called start
$("#someBtn").click(game.start); //in the method start this now point to the button so this.count is undefined.

What difference between This and That [duplicate]

This question already has answers here:
What does 'var that = this;' mean in JavaScript?
(6 answers)
Closed 8 years ago.
I'd like to know and understand the different between this and that, and when I have to use it.
I ready many post and many tutorial but I don't understand yet
this is my class
function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
this.service = function () {
console.log(this.member); // foo
console.log(that.member); // foo
return dec() ? that.member : null;
};
}
New
var myContainer = new Container('foo');
myContainer.service()
Calling myContainer.service() will return 'abc' the first three times it is called.
After that, it will return null
Why i have to do var that = this ??
this is a variable that gets the context of the current function (which depends on how it was called).
that has no special meaning. It is just a variable to which a value has been assigned.
In this particular case, that is assigned the value that this has while the Container is running, and is used inside the service function (but still has the value that is the context of the call to Container. Since service is a different function, its value of this could be different.
Normally, for this particular design of function, Container would be called as a constructor function (so this would be the instance object of Container) and then service would be called in the context of that instance object so you could use this instead of passing the value around via that. I have no idea why the author of that code chose to use that here.

Accessing this in anonymous function

I want to create a prototype function that has its own scope. For this, I use an anonymous function but I cannot find a way to access the members of the object.
Here is a simplified version of what I am trying to achieve:
function F() {
this.counter = 0;
}
F.prototype.increment = (function() {
var lastIncrementTime = -1;
var caller = this; // <--- it fails here because this is the Window object
return function(time) {
if (time > lastIncrementTime) {
caller.counter++;
lastIncrementTime = time;
return caller.counter;
}
return caller.counter;
}
})();
f = new F();
f.increment();
I know it fails because this does not refer to F or the f object.
Is there a way to access it?
The immediately invoked function expression (IIFE) itself only gets invoked once, all calls to increment will use the variables as they were last left and not re-var them.
Change the invocation context using call, apply or bind
F.prototype.increment = (function() {
// this === F.prototype
// ...
}).call(F.prototype);
The this in this example context will not be instance specific, but be the prototype.
It seems like you actually want to achieve something a little bit different, where you have an independent function to initialise an instance-specific property with it's own closure, when the instance is constructed. These types of actions can consume a bit of memory so don't store too much unique data.
function F() {
this.counter = 0;
this.__init_increment(); // create `this.increment`
}
F.prototype.__init_increment = function () {
var lastIncrementTime = -1;
this.increment = function (time) {
if (time > lastIncrementTime) {
this.counter++;
lastIncrementTime = time;
}
return this.counter;
};
};
var f = new F();
f.increment(0); // 1
f.increment(0); // 1
f.increment(5); // 2
In this example, this.increment is a different function for each instance, which means you have a different closure for each instance. They are generated by a function in the prototype, which sets the instance property. The generator does not have to be in the prototype, just remember about the invocation context when applying it to your instance.
Move your var caller = this inside the anonymous function, where this will have been set appropriately.

What is the exact use of closures in Javascript?

Hi still i'm not sure about the exact usage of using closures in javascript.I have idea about closures "A closure is an inner function that has access to the outer (enclosing) function’s variables—scope chain".But i don't know why we are using closures in javascript.
It allows you to succinctly express logic without needing to repeat yourself or supply a large number of parameters and arguments for a callback function.
There is more information available here: javascript closure advantages?
Imagine if instead of
alert("Two plus one equals" + (2+1) );
you'd be forced to declare a variable for every constant you ever use.
var Two = 2;
var One = 1;
var myString = "Two plus one equals";
alert(myAlert + (Two + One) );
You'd go crazy if you had to define a variable for every single constant before you can ever use it.
The access to local variables in case of closures is an advantage, but the primary role - usefulness - is the use of a function as a primary expression, a constant.
Take
function Div1OnClick()
{
Counter.clickCount ++;
}
$('#Div1').click(Div1OnClick);
versus
$('#Div1').click(function(){ Counter.clickCount++; });
You don't create a new function name in the "above" namespace just to use it once. The actual activity is right there where it's used - you don't need to chase it across the code to where it was written. You can use the actual function as a constant instead of first defining and naming it and then calling it by name, and while there are countless caveats, advantages and tricks connected to closures, that's the one property that sells them.
In general, the main use of closures is to create a function that captures the state from it's context. Consider that the function has the captured variables but they are not passed as parameters.
So, you can think of it of a way to create families of functions. For example if you need a series of function that only differ in one value, but you cannot pass that value as a parameter, you can create them with closures.
The Mozilla Developer Network has a good introduction to closures. It shows the following example:
function init() {
var name = "Mozilla";
function displayName() {
alert(name);
}
displayName();
}
init();
In this case the function displayName has captured the variable name. As it stand this example is not very useful, but you can consider the case where you return the function:
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
Here the function makeFunc return the function displayName that has captured the variable name. Now that function can be called outside by assigning it to the variable myFunc.
To continue with this example consider now if the captured variable name were actually a parameter:
function makeFunc(name) {
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc("Mozilla");
myFunc();
Here you can see that makeFunc create a function that shows a message with the text passed as parameter. So it can create a whole family of function that vary only on the value of that variable ("Mozilla" in the example). Using this function we can show the message multiple times.
What is relevant here is that the value that will be shown in the massage has been encapsulated. We are protecting this value in a similar fashion a private field of a class hides a value in other languages.
This allows you to, for example, create a function that counts up:
function makeFunc(value) {
function displayName() {
alert(value);
value++;
}
return displayName;
}
var myFunc = makeFunc(0);
myFunc();
In this case, each time you call the function that is stored in myFunc you will get the next number, first 0, next 1, 2... and so on.
A more advanced example is the "Counter" "class" also from the Mozilla Developer Network. It demonstrates the module pattern:
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
})();
alert(Counter.value()); /* Alerts 0 */
Counter.increment();
Counter.increment();
alert(Counter.value()); /* Alerts 2 */
Counter.decrement();
alert(Counter.value()); /* Alerts 1 */
Here you can see that Counter is an object that has a method increment that advances the privateCounter variable, and the method decrement that decrements it. It is possible to query the value of this variable by calling the method value.
The way this is archived is with an auto-invocation of an anonymous function that creates a hidden scope where the varialbe privateCounter is declared. Now this variable will only be accessible from the functions that capture its value.
Closures are a powerful construct used to implement a lot of additional features in JavaScript. For instance a closure can be used to expose private state as follows:
function getCounter() {
var count = 0;
return function () {
return ++count;
};
}
var counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
In the above example when we call getCounter we create a private variable count. Then we return a function which return count incremented. Hence the function we return is a closure in the sense that it closes over the variable count and allows you to access it even after count goes out of scope.
That's a lot of information stuffed in a few lines. Let's break it down?
Okay, so variables have a lifetime just like people do. They are born, they live and they die. The beginning scope marks the birth of a variable and the end of a scope marks the death of a variable.
JavaScript only has function scopes. Hence when you declare a variable inside a function it's hoisted to the beginning of the function (where it's born).
When you try to access a variable which is not declared you get a ReferenceError. However when you try to access a variable which is declared later on you get undefined. This is because declarations in JavaScript are hoisted.
function undeclared_variable() {
alert(x);
}
undeclared_variable();
When you try to access an undeclared variable you get a ReferenceError.
function undefined_variable() {
alert(x);
var x = "Hello World!";
}
undefined_variable();
When you try to access a variable which is declared later in the function you get undefined because only the declaration is hoisted. The definition comes later.
Coming back to scopes a variable dies when it goes out of scope (usually when the function within which the variable is declared ends).
For example the following program will give a ReferenceError because x is not declared in the global scope.
function helloworld() {
var x = "Hello World!";
}
helloworld();
alert(x);
Closures are interesting because they allow you to access a variable even when the function within which variable is declared ends. For example:
function getCounter() {
var count = 0;
return function () {
return ++count;
};
}
var counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
In the above program the variable count is defined in the function getCounter. Hence when a call to getCounter ends the variable count should die as well.
However it doesn't. This is because getCounter returns a function which accesses count. Hence as long as that function (counter) is alive the variable count will stay alive too.
In this case the function which is returned (counter) is called a closure because it closes over the variable count which is called the upvalue of counter.
Uses
Enough with the explanation. Why do we need closures anyway?
As I already mentioned before the main use of closures is to expose private state as is the case with the getCounter function.
Another common use case of closures is partial application. For instance:
function applyRight(func) {
var args = Array.prototype.slice.call(arguments, 1);
return function () {
var rest = Array.prototype.slice.call(arguments);
return func.apply(this, rest.concat(args));
};
}
function subtract(a, b) {
return a - b;
}
var decrement = applyRight(subtract, 1);
alert(decrement(1)); // 0
In the above program we had a function called subtract. We used partial application to create another function called decrement from this subtract function.
As you can see the decrement function is actually a closure which closes over the variables func and args.
That's pretty much all you need to know about closures.
It is because of information hiding.
var myModule = (function (){
var privateClass = function (){};
privateClass.prototype = {
help: function (){}
};
var publicClass = function (){
this._helper = new privateClass();
};
publicClass.prototype = {
doSomething: function (){
this._helper.help();
}
};
return {
publicClass: publicClass
};
})();
var instance = new myModule.publicClass();
instance.doSomething();
In javascript you don't have classes with ppp (public, protected, private) properties so you have to use closures to hide the information. On class level that would be very expensive, so the only thing you can do for better code quality to use closure on module level, and use private helper classes in that closure. So closure is for information hiding. It is not cheap, it cost resources (memory, cpu, etc..) so you have to use closures just in the proper places. So never use it on class level for information hiding, because it is too expensive for that.
Another usage to bind methods to instances by using callbacks.
Function.prototype.bind = function (context){
var callback = this;
return function (){
return callback.apply(context, arguments);
};
};
Typical usage of bound function is by asynchronous calls: defer, ajax, event listeners, etc...
var myClass = function (){
this.x = 10;
};
myClass.prototype.displayX = function (){
alert(this.x);
};
var instance = new myClass();
setTimeout(instance.displayX.bind(instance), 1000); //alerts "x" after 1 sec

JS function to return function, shares data which should be private

I'm trying to create a function which returns another function. I want separate information when each of the inner function is run, but this isn't happening. I know that explanation is not great, so I've put together a small example.
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return that;
})(testVal);
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());
This outputs 2, 2. What I would like is 2, 4 to be output. I know this isn't explained perfectly, so if it's not clear what I'm trying to achieve, can someone explain why the variable seems to be shared across the two functions?
Thanks
Like this ?
var testFn = function(testVal) {
var test = testVal
return {
getVal: function() {
return test
}
}
};
var ab = testFn (4)
var ac = testFn (2)
console.log(ab.getVal(),ac.getVal()) //4 //2
The problem in your code is this.getVal() / returning this
because 'this' refers to the global scope / Window
You are glubbering with the global namespace and overwriting Window.getVal() , the moment you are setting b = testFn (2)
This results in overwriting as method getVal too because they both refer to the global Object and always share the same method getVal
Therefore they share the same closure and are outputing 2
console.log("The same: " + (Window.a === Window.b)) // true
console.log("The same: " + (a === b)) // true
you can see that if you change it a little:
var testFn = function(testVal) {
var x = {}
return (function(testVal) {
var test = testVal;
x.getVal = function () {
return test;
}
return x
})(testVal);
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());//4 2
it suddenly works because it results in 2 different Objects returned (btw you don't even need the outer closure)
console.log("The same: " + (a === b)) // false
Here are the JSbins First / Second
I hope you understand this, I'm not good in explaining things
If theres anything left unclear, post a comment and I'll try to update the answer
This question comes down to the context in which functions are invoked in JavaScript.
A function that is invoked within another function is executed in the context of the global scope.
In your example, where you have this code:
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return this;
})(testVal);
}
The inner function is being called on the global scope, so this refers to the global object. In JavaScript a function executed within another function is done so with its scope set to the global scope, not the scope of the function it exists within. This tends to trip developers up a fair bit (or at least, it does me!).
For argument's sake, lets presume this is in a browser, so hence this refers to the window object. This is why you get 2 logged twice, because the second time this runs, this.getVal overwrites the getVal method that was defined when you ran var a = testFn(4);.
JavaScript scopes at function level, so every function has its own scope:
var x = 3;
function foo() {
var x = 2;
console.log(x);
};
console.log(x); //gives us 3
foo(); // logs 2
So what you want to do is run that inner function in the context of the testFn function, not in the global scope. You can run a function with a specific context using the call method. I also recorded a screencast on call and apply which discusses this in greater detail. The basic usage of call is:
function foo() {...}.call(this);
That executes foo in the context of this. So, the first step is to make sure your inner function is called in the right context, the context of the testFn method.
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return this;
}.call(this, testVal);
}
The first parameter to call is the context, and any arguments following that are passed to the function as parameters. So now the inner function is being called in the right scope, it wont add getVal to the global scope, which is a step in the right direction :)
Next though you also need to make sure that every time you call testFn, you do so in a new scope, so you're not overwriting this.getVal when you call testFn for the second time. You can do this using the new keyword. This SO post on the new keyword is well worth reading. When you do var foo = new testFn() you create and execute a new instance of testFN, hereby creating a new scope. This SO question is also relevant.
All you now need to do is change your declaration of a and b to:
var a = new testFn(4);
var b = new testFn(2);
And now console.log(b.getVal(), a.getVal()); will give 2, 4 as desired.
I put a working example on JSBin which should help clear things up. Note how this example defines this.x globally and within the function, and see which ones get logged. Have a play with this and hopefully it might be of use.
The output you get is (2,2) because when you do
var that = this;
what you actually get is the global object (window),
the object that holds all the global methods and variables in your javascript code.
(Note that every variable that is not nested under an object or function is global and
every function that is not nested under an object is global, meaning that functions that are nested under a function are still global)
so, when you set:
var test = testVal;
this.getVal = function() {
return test;
}
you actually set the function "getVal" in the global object, and in the next run you will again set the same function - overriding the first.
To achieve the affect you wanted I would suggest creating and object and returning it in the inner function (as #Glutamat suggested before me):
var testFn = function(testVal) {
return new Object({
getVal: function() {
return testVal;
}
});
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());
In this way, in the outer function we create an object with an inner function called "getVal" that returns the variable passed to the outer function (testVal).
Here's a JSBin if you want to play around with it
(thanks to #Glutamat for introducing this site, I never heard of it and it's really cool :D)

Categories

Resources