Why assign `this` to `self` and run `self.method()`? - javascript

I'm reading the source from mongoose
Collection.prototype.onOpen = function () {
var self = this;
this.buffer = false;
self.doQueue();
};
I don't understand why the author assigns this to self and runs self.doQueue(). Why not just run:
this.buffer = false;
this.doQueue();
I'm new to javascript, thanks for help.

You're right, in this instance they could have simply used this.
The use of me or self is a bit of a hack to ensure the correct context of this is used, as within JavaScript the scope of this is variant. If for example you have an event trigger a function within your class, this would be different, and wouldn't be your object that houses the function, but instead the object that called the function. To resolve this people often use me or self to ensure they're referring to the correct object... this, as in the actual object.

Just to give more clarity to #richard said earlier,
Collection.prototype.onOpen = function () {
var self = this;
this.buffer = false;
this.onclick = function(){
//do some other operations here
//if you refer `this` here then, `this` will refer to present function not the above. so to make sure it is referring to exact object people pass this to `me` or `self`
self.doQueue();
}
};

The only reason you would usually do that is if the call to doQueue() is inside a block that will change the value of this such as another function.
In this case however it doesn't serve any purpose and was probably a remnant of older code that was not changed back.

Most likely the developer wanted consistency, but failed at doing so.
Otherwise you'd be using this in some functions, self in other functions and a mix of both in other functions, depending on where you use the object and if you use nested functions/callbacks.
By always assigning this to self and then using the latter you have one additional assignment at the very beginning of each function but you always use self to access the object.
However, what the developer did in the code you posted does not make much sense. He should either use self or this both times instead of a mix that is not even necessary.

self is a copy of 'this',but it always refer to the right object,and 'this' may not.

Related

jQuery on change refer to this.value and this

Let's say I have a bit of code like this that runs on change of a select:
$('select[name="nights"]').on('change', function() {
console.log(this.value);
});
Is there any way I can have a reference to my global this object(if it's called that) without using something like:
var self = this;
Using something like a bind destroys the reference to the jQuery select element:
$('select[name="nights"]').on('change', function() {
console.log(this.value);
});
I wan't to be more concise and understanding of scope though so I prefer binding rather than saving reference to this. If I look at code standards from airbnb for example they rather not use self = this reference as well.
https://github.com/airbnb/javascript#naming--self-this
I am wondering how they get around this like stuff though where you both need a local scope reference to this and a this reference to your global object.
Am I simply forced to still make a reference or is there any way around this? I might simply be overthinking and nitpicking here but I am hoping for an elegant solution, else I might as well stick with saving references in the first place.
I'm not sure weather I understand your question.
With #bind (ES5 way)
$('select[name="nights"]').on('change', function(){
console.log(this.value);
}.bind(this));
From https://developer.mozilla.org/enUS/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
ES6 way
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Lexical this
Until arrow functions, every new function defined its own this value (a new object in case of a constructor, undefined in strict mode function calls, the context object if the function is called as an "object method", etc.). This proved to be annoying with an object-oriented style of programming.
An arrow function does not create its own this context; rather, it captures the this value of the enclosing context, so the following code works as expected.(I didn't copy the code)
so, you can to it with arrow function
$('select[name="nights"]').on('change', () => {
console.log(this.value);
});
NOTICE:
In your case i think you want to access the value of the select element, if so you
can use :
$(this).val();
instead of
this.value;
If you want to access the global this value, which is Window in the browser platform, you have two options:
Option 1:
If you want the ES5 way you can use an IIFE function, for example :
var that = (function(){return this;}());
option 2:
If you want the ES6 way, which is better with less code to write, for example:
const that = (()=>this)(); // .... (*)
Where (*) is the equivalent of the previous ES5 code.

Javascript: Create a sub-class within a class [duplicate]

I thought I had a reasonable understanding of the this object in JavaScript. When dealing with objects, callbacks, and both events and handlers, I haven't had a problem with it since time immemorial. Now, however, all has changed.
I've fallen head over heels in love with JavaScript. Pure JS, that is, not jQuery, prototype.js, dojo... So naturally, I've taken to using closures. In some cases, though, this is catching me off guard here. Take this snippet for one:
function anyFunc(par)
{
//console.log(par);
console.log(this);
}
function makeClosure(func)
{
return function(par)
{
return func(par);
}
}
var close = makeClosure(anyFunc);
close('Foo');
var objWithClosure = {cls:makeClosure(anyFunc),prop:'foobar'};
objWithClosure.cls(objWithClosure.prop);
var scndObj = {prop:'Foobar2'};
scndObj.cls = makeClosure;
scndObj.cls = scndObj.cls(anyFunc);
scndObj.cls(scndObj.prop);
In all three cases, this logs as the window object. It's an easy fix, of course:
function makeClosure(func)
{
return function(par)
{
return func.call(this,par);
}
}
This fix works, I put it here to avoid people answering this, without explaining what I need to know: why is this behaving the way it does here?
ensures the caller is effectively the object that the closure belongs to. What I fail to understand is this:
Sure enough, this points to the window object in the first case, but in other cases, it shouldn't. I tried logging this in the makeClosure function just before returning, and it did log the object itself, not the window object. But when the actual closure is used, this is back to pointing to the window object. Why?
The only thing I can think of is that, by passing the anyFunc function as an argument, I'm actually passing window.anyFunc. So I tried this quick fix:
function makeClosure(func)
{
var theFunc = func;
return function(par)
{
theFunc(par);
}
}
With the expected results, this now points to the objects, but again: Why? I have a few idea's (theFunc is a reference to the function in the local scope [this > private: theFunc]?), but I'm sure there are people here with a lot more know-how when it comes to JS, so I was hoping to get some more explanation or links to articles worth reading from them...
Thanks
Update
Here's a fiddle, may be I left something out, but here this logs all sorts of things ;)
Edit/Update 2
The case that confuses me is here.
Final Edit
Ok, This is getting a rather messy post. So to clarify: What I was expecting was a behaviour similar to this:
function makeClosure()
{
function fromThisFunc()
{
console.log(this);
}
return fromThisFunc;
}
var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();
What caught me, was that the function anyFunc wasn't declared within the correct scope, and therefore, this pointed to the window object. I found this out by reading an ancient scroll I found somewhere on the web.
But something a little more complicated has happened because the function object now referred to by globalVar was created with a [[scope]] property referring to a scope chain containing the Activation/Variable object belonging to the execution context in which it was created (and the global object). Now the Activation/Variable object cannot be garbage collected either as the execution of the function object referred to by globalVar will need to add the whole scope chain from its [[scope]] property to the scope of the execution context created for each call to it.
So what I needed to do, was simplify rather then complicate things:
function fromThisFunc()
{
console.log(this);
}
function makeClosure(funcRef)
{
//some code here
return funcRef;
}
That should work, right?
PS: I'll except Alnitak's answer, but special thanks goes to Felix Kling for all the patience and info.
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 )
The value of this depends only on whether you call the function as a method or as a function.
If you call it as a method, this will be the object that the method belongs to:
obj.myFunction();
If you call it as a function, this will be the window object:
myFunction();
Note that even if you are in a method that belongs to an object, you still have to call other methods in the object using the method syntax, otherwise they will be called as functions:
this.myOtherFunction();
If you put a method reference in a variable, you will detach it from the object, and it will be called as a function:
var f = obj.myFunction;
f();
The call and apply methods are used to call a function as a method even if it's not a method in the object (or if it's a method in a different object):
myFunction.call(obj);

What's the advantage of using `var self = this` in knockout.js view models [duplicate]

This question already has answers here:
var self = this?
(8 answers)
Closed 9 years ago.
I see in almost all examples of a knockout.js viewmodels the line var self = this and then all local variables are references as self.variableName. What is the advantage of this over using this.variableName?
Normally the main reason for using this approach is to make the current this available to subfunctions or closures. For example:
var myObject = {
param: 123,
method: function(){
alert( this.param );
},
method2: function(){
setTimeout(function(){
alert( this.param );
},100);
}
}
In the above calling myObject.method will give you the correct alert of 123. However calling myObject.method2 will give you undefined. This is because this inside the anonymous function used with setTimeout does not refer to myObject, depending on the JavaScript interpreter it will point to different things. However, if you have:
method2: function(){
var self = this;
setTimeout(function(){
alert( self.param );
},100);
}
This works because the current state of this — at the right point — is captured, and will always reference myObject for every function scope that it is available to.
The problem is not limited to the use of setTimeout. At any point where you have anonymous functions, subfunctions or closures this trick will come in handy. Sometimes people use self, or that or something a bit more descriptive depending on what the current reference represents.
rather than storing as a variable
There is an alternative to using self or any other variable to "remember" the state of this at any particular point, and that is to "bind" your anonymous or sub functions with a particular context. Many modern interpreters now support the Function.prototype.bind method, which can be used thusly:
var method = function(){
console.log(this);
};
var methodWithWindow = method.bind(window);
var methodWithDocument = method.bind(document);
var methodWithObject = method.bind({random:"object"});
Calling each of the bound methods in turn would give you the following console output:
Window
Document
Object {random:"object"}
If you wish to support older browsers you can use a polyfill, or if you prefer a much simpler implementation, one that doesn't worry about binding arguments as well. The basics of what the bind code does is the following:
!Function.prototype.bind && (Function.prototype.bind = function(context){
var method = this;
return function(){
method.apply(context, arguments);
}
})
So, how would the initial example look using bind?
method2: function(){
setTimeout((function(){
console.log(this); // `this` will be the same as the `this` passed to bind.
}).bind(this),100);
}
As you can see above, once bound, the returned function (closure) retains that specified context; so it can be passed around where ever you want and still keep a this reference to the object you want. This is useful in the method2 example because we bundle the method up with our current context and pass it to setTimeout which will execute the bound method later (long after we have exited the current block execution).
The same does occur for when using self or any other variable. The variable would be captured within the function's scope chain, and would still be there for access when the function is eventually called again. The benefit of using bind however is that you can override the context easily if you so wish, you would have to code your own specific methods to do so to override a self variable.
WARNING: It is worth noting here that when you bind a function, a new function is returned. This can cause confusing situations if you mix bound functions with event listeners and then attempt to remove the listeners using the original function rather than the bound version.
Also, because binding returns a new function, if you bind a bound function you are in fact wrapping a function in a function, with another function. You should be aware of this because it affects performance and will prove trickier to manage in terms of avoiding memory leaks. My preferred approach to binding is to use closures with their own deconstruction methods (i.e. rely on self, but make sure you have methods to nullify it's content), but this does take more forward thinking and is not so relevant in smaller JS projects; or one off function bindings — especially if the bound method is never caught in any reference.
without self and bind?
It is also worth mentioning that sometimes you can achieve the same result without using bind at all, and instead use apply — which should be natively available in anything you may choose to use. The major difference being that nothing is wrapped up with the function, and calling apply actually executes the function there and then with a different context — the first argument passed to apply.
var externalMethod = function(){
console.log(this); // will output myObject when called below
};
var myObject = {
method2: function(){
externalMethod.apply(this);
}
};
What is this?
Just to elaborate this answer with further detail about this — before the recent comments get deleted. this will refer to one of four things, depending on how the function you are using it within was called:
myObject.method()
The above will have a this of myObject, unless method has had a .bind(context) operation applied. In which case this will be whatever the last bound context was.
unattachedFunction()
Will have a this of the global context (usually window in browser environments), unless unattachedFunction has had a .bind(context) operation applied. In which case this will be whatever the last bound context was.
anyFunction.apply(otherObject)
or
anyFunction.call(otherObject)
Both will always have a this of otherObject, because calling in this way will override any binding.
new myObject()
Will have a this that refers to a new instance of myObject, this will override any binding.
Simple thought experiment
Taking all the above into account, what would this be inside referencedMethod?
var referencedMethod = myObject.method;
referencedMethod();
Correct! it will be the global context. This is why if you want to share methods with other objects or code — but still retain the original owner as context — you really need to either bind, or keep the function bundled with its owner object so you can call or apply.
Self is used to make sure the original this is maintained within the object.
This comes in handy when using event handlers and so on.
You can read more about this here
The first answer covers it basically, also it shows a good link. Check it out.
It is used for reference purposes. this under Javascript behaves different than in other languages. For more details look at MDN Docs on this

JavaScript closure and the this object

I thought I had a reasonable understanding of the this object in JavaScript. When dealing with objects, callbacks, and both events and handlers, I haven't had a problem with it since time immemorial. Now, however, all has changed.
I've fallen head over heels in love with JavaScript. Pure JS, that is, not jQuery, prototype.js, dojo... So naturally, I've taken to using closures. In some cases, though, this is catching me off guard here. Take this snippet for one:
function anyFunc(par)
{
//console.log(par);
console.log(this);
}
function makeClosure(func)
{
return function(par)
{
return func(par);
}
}
var close = makeClosure(anyFunc);
close('Foo');
var objWithClosure = {cls:makeClosure(anyFunc),prop:'foobar'};
objWithClosure.cls(objWithClosure.prop);
var scndObj = {prop:'Foobar2'};
scndObj.cls = makeClosure;
scndObj.cls = scndObj.cls(anyFunc);
scndObj.cls(scndObj.prop);
In all three cases, this logs as the window object. It's an easy fix, of course:
function makeClosure(func)
{
return function(par)
{
return func.call(this,par);
}
}
This fix works, I put it here to avoid people answering this, without explaining what I need to know: why is this behaving the way it does here?
ensures the caller is effectively the object that the closure belongs to. What I fail to understand is this:
Sure enough, this points to the window object in the first case, but in other cases, it shouldn't. I tried logging this in the makeClosure function just before returning, and it did log the object itself, not the window object. But when the actual closure is used, this is back to pointing to the window object. Why?
The only thing I can think of is that, by passing the anyFunc function as an argument, I'm actually passing window.anyFunc. So I tried this quick fix:
function makeClosure(func)
{
var theFunc = func;
return function(par)
{
theFunc(par);
}
}
With the expected results, this now points to the objects, but again: Why? I have a few idea's (theFunc is a reference to the function in the local scope [this > private: theFunc]?), but I'm sure there are people here with a lot more know-how when it comes to JS, so I was hoping to get some more explanation or links to articles worth reading from them...
Thanks
Update
Here's a fiddle, may be I left something out, but here this logs all sorts of things ;)
Edit/Update 2
The case that confuses me is here.
Final Edit
Ok, This is getting a rather messy post. So to clarify: What I was expecting was a behaviour similar to this:
function makeClosure()
{
function fromThisFunc()
{
console.log(this);
}
return fromThisFunc;
}
var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();
What caught me, was that the function anyFunc wasn't declared within the correct scope, and therefore, this pointed to the window object. I found this out by reading an ancient scroll I found somewhere on the web.
But something a little more complicated has happened because the function object now referred to by globalVar was created with a [[scope]] property referring to a scope chain containing the Activation/Variable object belonging to the execution context in which it was created (and the global object). Now the Activation/Variable object cannot be garbage collected either as the execution of the function object referred to by globalVar will need to add the whole scope chain from its [[scope]] property to the scope of the execution context created for each call to it.
So what I needed to do, was simplify rather then complicate things:
function fromThisFunc()
{
console.log(this);
}
function makeClosure(funcRef)
{
//some code here
return funcRef;
}
That should work, right?
PS: I'll except Alnitak's answer, but special thanks goes to Felix Kling for all the patience and info.
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 )
The value of this depends only on whether you call the function as a method or as a function.
If you call it as a method, this will be the object that the method belongs to:
obj.myFunction();
If you call it as a function, this will be the window object:
myFunction();
Note that even if you are in a method that belongs to an object, you still have to call other methods in the object using the method syntax, otherwise they will be called as functions:
this.myOtherFunction();
If you put a method reference in a variable, you will detach it from the object, and it will be called as a function:
var f = obj.myFunction;
f();
The call and apply methods are used to call a function as a method even if it's not a method in the object (or if it's a method in a different object):
myFunction.call(obj);

Javascript question: Problem with calling an objects methods

Say I have an object called FieldEdit. I define the function constructor for this object, instantiate it via. var obj = new FieldEdit(), and define its methods by FieldEdit.prototype.<method name> = function() { ... }.
Under what situations would calling this object's methods within the objects' other methods (via. this.<method name>();) fail?
Note that I want to avoid posting a code sample for this if I can since I think this is simply a problem with my understanding of Javascript more than anything, really. I'm pretty sure my code is sound, to the best of my knowledge (and it's my knowledge that's the question here, besides).
The most likely scenario where this would reference an object other than FieldEdit during execution of FieldEdit methods is within a nested scope like a closure, an event handler, or any function or method called explicitly with .call(someOtherScope) or .apply(someOtherScope, args).
You can work around that, of course, by maintaining a variable reference to the FieldEdit instance and using FieldEditInstance.<method>() instead.
PrototypeJS allows you to wrap functions with Function.bind for this purpose, but it's easily accomplished otherwise, either with:
var FieldEditInstance = this;
obj.methodThatUsesACallback(function() {
// use that instead of this
});
OR
var FieldEditInstance = this;
var callback = function() {
// ...
};
// This is more or less what PrototypeJS' Function.bind produces
var boundCallback = function() {
return callback.apply(FieldEditInstance, arguments);
};
obj.methodThatUsesACallback(boundCallback);

Categories

Resources