This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript: Object Literal reference in own key’s function instead of ‘this’
I have this simple code :
var myObj = {
init: function ()
{
this.Name = "Royi";
this.BindMe();
}
BindMe: function ()
{
$('myButton').on("click", this.Work);
},
Work: function ()
{
var self = this; <--------
}
}
Running :
myObj.init();
This is a simple Object literal.
The problem is on the Work Method. I want to make it know this ( myObj)
there are 2 ways of doing it :
option #1
In BindMe , When clicking , transfer the context via :
$('myButton').on("click",{self:this}, this.Work);
and in Work do :
var self = e.data.self... //need also to add e
option #2
write var self = myObj ;
Question
Is there any other way of doing it ?
which is the better/correct way ?
Don't add it as data to the event object. Instead, use .bind() or the jQuery-ish (crossbrowser) proxy to provide the correct thisArg to the function (see MDN's introduction to the this keyword):
$('myButton').on("click", $.proxy(this, "Work"));
You could pass the context to the handler function as part of a closure:
$('myButton').on("click", (function(context) {
return function() {
context.Work
};
})(this));
Needless to say, this is cross browser, since it relies on one of the core features of JS.
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
I am using Typescript for an Angular 2 project. I notice that when we use the keyword this inside a labmda expression vs a function, this refers to different things.
For example, let's say I have an Angular component like the following.
export class MyComponet {
isActive = true;
names = [ "john", "jeff", "jared" ];
doSomethingWithLambda() {
names.forEach( (value, index) => {
if(this.isActive) { //this.isActive refers to MyComponent.isActive
//do something...
}
});
}
doSomethingWithFunction() {
names.forEach( function(value, index) {
if(this.isActive) { //this.isActive is undefined, since this refers to the function
//do something
}
});
}
doSomethingWithFunction2() {
let isActive = this.isActive;
names.forEach( function(value, index) {
if(isActive) { //if we change isActive will this also change MyComponent.isActive?
//do something
}
});
}
}
What is really happening here (behind the scene, so to speak)? What's the magic behind this inside a lambda that makes it able to "correctly" refer to the outer class' fields? I understand this inside a function will refer to the function itself.
Also, I have a doSomethingWithFunction2 method that will reference MyComponent.isActive into a local variable. If I change that local variable, that should be like changing the one it references, right? (regardless of it being a "primitive" like integer/number or an "object" like JSON { })
The fat-arrow function syntax is shorthand for:
function () { }.bind(this);
bind is a Javascript ES5 method equivalent to this:
Function.prototype.bind = function bind(context) {
var func = this;
return function () {
return func.apply(context, arguments);
};
}
In regards to
Also, I have a doSomethingWithFunction2 method that will reference MyComponent.isActive into a local variable. If I change that local variable, that should be like changing the one it references, right? (regardless of it being a "primitive" like integer/number or an "object" like JSON { })
In Javascript, variables are like pointers and except for some limited cases (primitives and copy-on-write objects) will change the referenced value when mutated. Reassigning will not change the original value, e.g. isActive = false; but this.isActive = false would in fact re-assign the variable isActive on this which is now hopefully correctly assigned.
This has to do with how lambda function are implement in TS. this in arrow function is lexically inferred so it more in line with below code
function Person() {
var self = this; // Some choose that instead of self.
// Choose one and be consistent.
self.age = 0;
setInterval(function growUp() {
// The callback refers to the self variable of which
// the value is the expected object.
self.age++;
}, 1000);
}
So inside the lambda function it is not actually this but a context closer self. This may not be actual implementation but much closer to give you understanding of what is happening.
Now when you are outside the my impotent this refers to global var which would be window
The lambda function is similar to javascripts bind function.
Protip see your transpiled JS how your lambda function is transforming.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a function in the following format:
var obj = {
doSomething: function(){
this.callSomething();
},
callSomething: function(){
this.doThis();
this.andDoThis();
},
doThis: function(){
if(!this.bln){
this.bln = true;
}
// some code here
},
andDoThis: function(){
if(this.bln){
// some code here
}
}
}
obj.doSomething();
As you can see in the above code, I am using this keyword many times to call a function or a obj scoped variables.
Instead of using this keyword, I want to use something of single letter like:
var s = this; // so that I can use "s" instead of "this" everywhere
How can I do this?
PS: Here obj object name is just for example purpose. In real scenario, the object name is longer than this keyword.
You can get rid of this entirely if you use the module or the revealing module patterns.
The following example uses the revealing module pattern:
var module = (function() {
var bln = false,
doSomething = function() { callSomething(); },
callSomething = function() { doThis(); andDoThis(); },
doThis = function() { if (!bln) { bln = true; } },
andDoThis = function() { if (bln) { /* do stuff */ } };
return {
doSomething: doSomething //Only public method, rest are private
};
})();
module.doSomething();
Try this. Variable name itself can be used as this inside that object.
var longName = s = {
doSomething: function(){
s.callSomething();
},
callSomething: function(){
s.doThis();
s.andDoThis();
},
doThis: function(){
if(!s.bln){
s.bln = true;
}
// some code here
}
...........................
}
Hi probably the above answers are correct, BUT its not a good way to do things.
It will be way harder to read your code if you go away from "this". Reading "this" you always know you are talking about the reference of your object instance.
The only reason i can think of where this could be usefull is to reduce memory by 3 byte for each "this" you replace by "s".
You would have to define s on a global scope to achieve what you actually want - which is VERY dangerous.
There is alot of blackboxing you do in javascript by implementing eg. frameworks that might ruin everything for you.
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
I have a normal object in javascript, contenting functions and values.
This is my example object:
var MyObject = {
myData: 1,
a: function() {},
b: function() {}
}
Now in the function a there is some logic that fire on it, but it should change even the value of myData property.
But when i try get it from the method b, that value come as an undefined value, instead of the value changed.
I created a JsFiddle with a small example of the behaviour of the my object. I realized that it how Javascript behave, but I didn't understand why.
The issue is because this within the click handlers refers to the element which was clicked, not the object the handler functions are members of. You need to cache this:
a: function () {
var self = this;
$('.setValue').click(function() {
self.myData = 2;
});
},
b: function () {
var self = this;
$('.getValue').click(function() {
alert(self.myData);
});
}
Updated fiddle
In JavaScript, each function has its own this argument. In your case, you want to access the outer function's this variable so you should do something like this:
var that = this;
Here is the updated jsfiddle:
http://jsfiddle.net/xaaLQ/5/
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 1 year ago.
Normally I'd assign an alternative "self" reference when referring to "this" within setInterval. Is it possible to accomplish something similar within the context of a prototype method? The following code errors.
function Foo() {}
Foo.prototype = {
bar: function () {
this.baz();
},
baz: function () {
this.draw();
requestAnimFrame(this.baz);
}
};
Unlike in a language like Python, a Javascript method forgets it is a method after you extract it and pass it somewhere else. You can either
Wrap the method call inside an anonymous function
This way, accessing the baz property and calling it happen at the same time, which is necessary for the this to be set correctly inside the method call.
You will need to save the this from the outer function in a helper variable, since the inner function will refer to a different this object.
var that = this;
setInterval(function(){
return that.baz();
}, 1000);
Wrap the method call inside a fat arrow function
In Javascript implementations that implement the arrow functions feature, it is possible to write the above solution in a more concise manner by using the fat arrow syntax:
setInterval( () => this.baz(), 1000 );
Fat arrow anonymous functions preserve the this from the surrounding function so there is no need to use the var that = this trick. To see if you can use this feature, consult a compatibility table like this one.
Use a binding function
A final alternative is to use a function such as Function.prototype.bind or an equivalent from your favorite Javascript library.
setInterval( this.baz.bind(this), 1000 );
//dojo toolkit example:
setInterval( dojo.hitch(this, 'baz'), 100);
i made a proxy class :)
function callback_proxy(obj, obj_method_name)
{
instance_id = callback_proxy.instance_id++;
callback_proxy.instances[instance_id] = obj;
return eval('fn = function() { callback_proxy.instances['+instance_id+'].'+obj_method_name+'(); }');
}
callback_proxy.instance_id = 0;
callback_proxy.instances = new Array();
function Timer(left_time)
{
this.left_time = left_time; //second
this.timer_id;
this.update = function()
{
this.left_time -= 1;
if( this.left_time<=0 )
{
alert('fin!');
clearInterval(this.timer_id);
return;
}
}
this.timer_id = setInterval(callback_proxy(this, 'update'), 1000);
}
new Timer(10);
This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 9 years ago.
So, I am not a JavaScript expert, just trying to understand what the difference is between two following snippets of code. I have a project that I want to convert to TypeScript and I need to understand the difference between two code snippets being generated.
var Pony = (function () {
function Pony() { }
Pony.prototype.bite = function () {
alert("Chomp!");
};
return Pony;
})();
var Pony2 = (function () {
function Pony2() {
var self = this;
self.bite = function () {
alert("Chomp!");
};
}
return Pony2;
})();
The difference between the two is that you can get to the prototype of the first Pony via attributes on the object stored in var Pony and could expand upon or use the associated bits of that prototype elsewhere where as Pony2 would just be considered a function. So if you do not plan on using any sort of prototypical inheritance later on they are equivalent.
The answers above give a good overview on the difference between putting on the prototype and putting on the instance. As to your question about converting to TypeScript, below is how you would write them both:
class Pony {
bite(){
alert('chomp');
}
}
class Pony2 {
bite: () => void;
constructor(){
this.bite = () => alert('chomp');
}
}
As far as how you use them, there's no difference. However, from a performance standpoint the former method would be preferable. Let's extend your example a little bit:
var prototypePony1 = new Pony();
var prototypePony2 = new Pony();
var thisPony1 = new Pony2();
var thisPony2 = new Pony2();
prototypePony1.hasOwnProperty('bite'); //returns false
prototypePony2.hasOwnProperty('bite'); //returns false
thisPony1.hasOwnProperty('bite'); //returns true
thisPony2.hasOwnProperty('bite'); //returns true
Pony.prototype.bite = function() { alert('Nomnomnom!'); };
Pony2.prototype.bite = function() { alert('Nomnomnom!'); };
prototypePony1.bite(); //alerts 'Nomnomnom!'
prototypePony2.bite(); //alerts 'Nomnomnom!'
thisPony1.bite(); //alerts 'Chomp!', instance property is accessed first
delete thisPony2.bite;
thisPony2.hasOwnProperty('bite'); //returns false
thisPony2.bite(); //alerts 'Nomnomnom!'
In the example above, thisPony1 and thisPony2 both get their own copy of the bite function, since it was defined using this However, prototypePony1 and prototypePony2 both share the same copy of bite from Pony's constructor.
Once we define the bite prototype on Pony2, the instance property is still accessed first on thisPony1. It's not until we delete the instance property that we see the newly defined prototype property on thisPony2.
For more detailed info on defining object methods, have a look here.