Assigning this to inner variable say ""self [duplicate] - javascript

I saw the following in the source for WebKit HTML 5 SQL Storage Notes Demo:
function Note() {
var self = this;
var note = document.createElement('div');
note.className = 'note';
note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
note.addEventListener('click', function() { return self.onNoteClick() }, false);
this.note = note;
// ...
}
The author uses self in some places (the function body) and this in other places (the bodies of functions defined in the argument list of methods). What's going on? Now that I've noticed it once, will I start seeing it everywhere?

See this article on alistapart.com. (Ed: The article has been updated since originally linked)
self is being used to maintain a reference to the original this even as the context is changing. It's a technique often used in event handlers (especially in closures).
Edit: Note that using self is now discouraged as window.self exists and has the potential to cause errors if you are not careful.
What you call the variable doesn't particularly matter. var that = this; is fine, but there's nothing magic about the name.
Functions declared inside a context (e.g. callbacks, closures) will have access to the variables/function declared in the same scope or above.
For example, a simple event callback:
function MyConstructor(options) {
let that = this;
this.someprop = options.someprop || 'defaultprop';
document.addEventListener('click', (event) => {
alert(that.someprop);
});
}
new MyConstructor({
someprop: "Hello World"
});

I think the variable name 'self' should not be used this way anymore, since modern browsers provide a global variable self pointing to the global object of either a normal window or a WebWorker.
To avoid confusion and potential conflicts, you can write var thiz = this or var that = this instead.

Yes, you'll see it everywhere. It's often that = this;.
See how self is used inside functions called by events? Those would have their own context, so self is used to hold the this that came into Note().
The reason self is still available to the functions, even though they can only execute after the Note() function has finished executing, is that inner functions get the context of the outer function due to closure.

It should also be noted there is an alternative Proxy pattern for maintaining a reference to the original this in a callback if you dislike the var self = this idiom.
As a function can be called with a given context by using function.apply or function.call, you can write a wrapper that returns a function that calls your function with apply or call using the given context. See jQuery's proxy function for an implementation of this pattern. Here is an example of using it:
var wrappedFunc = $.proxy(this.myFunc, this);
wrappedFunc can then be called and will have your version of this as the context.

As others have explained, var self = this; allows code in a closure to refer back to the parent scope.
However, it's now 2018 and ES6 is widely supported by all major web browsers. The var self = this; idiom isn't quite as essential as it once was.
It's now possible to avoid var self = this; through the use of arrow functions.
In instances where we would have used var self = this:
function test() {
var self = this;
this.hello = "world";
document.getElementById("test_btn").addEventListener("click", function() {
console.log(self.hello); // logs "world"
});
};
We can now use an arrow function without var self = this:
function test() {
this.hello = "world";
document.getElementById("test_btn").addEventListener("click", () => {
console.log(this.hello); // logs "world"
});
};
Arrow functions do not have their own this and simply assume the enclosing scope.

It's a JavaScript quirk. When a function is a property of an object, more aptly called a method, this refers to the object. In the example of an event handler, the containing object is the element that triggered the event. When a standard function is invoked, this will refer to the global object. When you have nested functions as in your example, this does not relate to the context of the outer function at all. Inner functions do share scope with the containing function, so developers will use variations of var that = this in order to preserve the this they need in the inner function.

The variable is captured by the inline functions defined in the method. this in the function will refer to another object. This way, you can make the function hold a reference to the this in the outer scope.

Actually self is a reference to window (window.self) therefore when you say var self = 'something' you override a window reference to itself - because self exist in window object.
This is why most developers prefer var that = this over var self = this;
Anyway; var that = this; is not in line with the good practice ... presuming that your code will be revised / modified later by other developers you should use the most common programming standards in respect with developer community
Therefore you should use something like var oldThis / var oThis / etc - to be clear in your scope // ..is not that much but will save few seconds and few brain cycles

As mentioned several times above, 'self' is simply being used to keep a reference to 'this' prior to entering the funcition. Once in the function 'this' refers to something else.

function Person(firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
this.getfullname = function () {
return `${this.firstname} ${this.lastname}`;
};
let that = this;
this.sayHi = function() {
console.log(`i am this , ${this.firstname}`);
console.log(`i am that , ${that.firstname}`);
};
}
let thisss = new Person('thatbetty', 'thatzhao');
let thatt = {firstname: 'thisbetty', lastname: 'thiszhao'};
thisss.sayHi.call(thatt);

Related

Classes and methods javascript [duplicate]

Below I am creating an object in JavaScript. Within the constructor I am setting up an event listener. The problem is that when the event gets fired, this.prop cannot be found, and undefined prints out. How do I solve this?
var someObj = function someObj(){
this.prop = 33;
this.mouseMoving = function() { console.log(this.prop);}
document.getElementById("someDiv").addEventListener('mousemove', this.mouseMoving, true);
}
When the event handler gets called, "this" no longer references the "someObj" object. You need to capture "this" into a local variable that the mouseMoving function will capture.
var someObj = function someObj(){
this.prop = 33;
var self = this;
this.mouseMoving = function() { console.log(self.prop);}
document.getElementById("someDiv").addEventListener('mousemove', this.mouseMoving, true);
}
I'm assuming "someObj is a constructor, i.e. intended to be called with as new someObj(), otherwise "this" will be the global scope.
The "this" keyword can be confusing in JavaScript, because it doesn't work the same way as in other languages. The key thing to remember is that it is bound to the calling object when the function is called, not when the function is created.
The javascript built-in Function.prototype.bind() is intended for this purpose.
For example:
var someObj = function someObj(){
this.prop = 33;
this.mouseMoving = function() { console.log(this.prop);}
document.getElementById("someDiv").addEventListener('mousemove', this.mouseMoving.bind(this),true);
}
More on the bind method here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
Other wise you have to pass a reference of the object someObj to the element and use that reference in the line:
console.log(this.referenceToObject.prop); //this references the DOM element in an event.
From Section 4.3 of JavaScript: The Good Parts by Douglas Crockford:
Invoking a function suspends the
execution of the current function,
passing control and parameters to the
new function. In addition to the
declared parameters, every function
receives two additional parameters:
this and arguments. The this parameter
is very important in object oriented
programming, and its value is
determined by the invocation pattern.
There are four patterns of invocation
in JavaScript: the method invocation
pattern, the function invocation
pattern, the constructor invocation
pattern, and the apply invocation
pattern. The patterns differ in how
the bonus parameter this is
initialized.
Crockford continues to explains the binding of 'this' in each of these patterns, as follows:
The Method Invocation Pattern:
When a function is stored as a property of an object, we call it a method. When a method is invoked, this is bound to that object.
The Function Invocation Pattern:
When a function is invoked with this pattern, this is bound to the global object. This was a mistake in the design of the language.
The Constructor Invocation Pattern:
If a function is invoked with the new prefix, then a new object will be created with a hidden link to the value of the function's prototype member, and this will be bound to that new object.
The Apply Invocation Pattern:
The apply method lets us construct an array of arguments to use to invoke a function. It also lets us choose the value of this. The apply method takes two parameters. The first is the value that should be bound to this. The second is an array of parameters.
You could use a variable named 'me', to avoid conflict with the global JavaScript variable 'self':
function someObj() {
var me = this;
this.prop = 33;
this.mouseMoving = function() {
alert(me.prop);
}
document.getElementById("someDiv").addEventListener('mousemove', this.mouseMoving, true);
}
First, you need to understand how 'this' works in JavaScript. 'this' keyword doesn't behave how it behaves in other languages like C# or Java. Read following post to understand more,
What is the rationale for the behavior of the 'this' keyword in JavaScript?
Once you understand that, as Matthew outlined in his code, you can save reference to 'this' and use that reference inside the mouseMoving function.
Though overall, I will advise that you use a JavaScript framework (e.g. jQuery, YUI, MooTools) which will take care of these issues for you. E.g. In Internet Explorer, you use addEvent to attach event and not addEventListenr.
You have some typos on your function declaration.
Your prop variable is also defined as a "public" or "visible" member (by using this.prop), doing so forces you to store the reference of this from the outer function (that is actually a reference to the object instance), as a "private" member of the function (using var) to get access the instance of the created object and read the "public" prop member.
You have some alternatives to rewrite this code:
function someObj (){
var self = this;
this.prop = 33;
this.mouseMoving = function() { alert(self.prop);} // You access the current
// instance, stored in *self*
// since *this*, inside the
// function, is in another
// context.
//...
}
var mySomeObj = new someObj(); // Object instantiation
Or you could:
function someObj (){
var prop = 33;
this.mouseMoving = function() { alert(prop);}
//...
}
var mySomeObj = new someObj(); // Object instantiation
The variables declared with var, are accesible to the functions declared inside of the major constructor function, this feature is known as Closures.

JS how to avoid using "this" [duplicate]

This question already has answers here:
Difference between this and self in JavaScript
(5 answers)
Closed 4 years ago.
I recently watched a youtube tutorial, and the guy did something interesting in the series (it's node.js game tutorials by Raining Chain). His constructor looks like this:
const MakeStuff = function(param1, param2) {
const self = {};
self._param1 = param1;
self._param2 = param2;
// and so on...
return self;
}
const someStuff = MakeStuff(param1, param2);
I then checked google for what "self" meant and it found out it's something similar to "this"... It's really confusing me now. At first I thought he's just naming it "self" to mimic "this", but avoid using it.
Also, JSLint really hates "this", and I hate to dumb down JSLint and disable or edit options (ocd), so I'm trying to figure out how am I gonna use classes, and avoid using "this" inside classes constructor.
I figured I'd copy/paste my class function in babeljs and see what the class syntax actually does under the hood, but I got even more confused.
I have around 2k lines of code in my game, and 1.5k are just classes with getters, setters and static methods.
What does the code above actually do? What does self mean? Can I use JS classes and avoid using "this" in constructors? Why does JSLint even hate "this"? Should I rework my code using the example above and bind getters, setters and static methods using prototype?
Thanks!
What does the code above actually do?
const MakeStuff = function(param1, param2) {
const self = {};
console.log(self);
self._param1 = param1;
self._param2 = param2;
// and so on...
return self;
}
const someStuff = MakeStuff(1, 2);
console.log(someStuff)
This above code simply calls a function which accepts two parameter and return an object.self inside this function is merely a variable
What does self mean?
Unless specifically set self refers to the window object.But in the above function const self is not window.self
console.log(self)
As of now, self is used by other languages in place of js' this; it is a reference to the instance's context. In this use case, he's not writing a constructor, but a factory. self is little more than a naming convention here. It would make no difference if he wrote:
const MakeStuff = function(param1, param2) {
const obj = {};
obj._param1 = param1;
obj._param2 = param2;
// and so on...
return obj;
}
const someStuff = MakeStuff(param1, param2);
Also, +1 to brk for mentioning that self, unless re-set, references window.
this is one of the important aspects of JavaScript but one of the most poorly understood. It is absolutely essential to understand to do any Object Oriented Programming within JS which is essential to game design.
I would recommend learning about scope and how this applies to different things in different scopes.
http://web.archive.org/web/20110725013125/http://www.digital-web.com/articles/scope_in_javascript/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
https://javascriptplayground.com/javascript-variable-scope-this/
http://ryanmorr.com/understanding-scope-and-context-in-javascript/
Essentially when you run a function such as
function window_scope() {
this.foobar;
}
this is the window in browsers or whatever variable is defined as the global scope. Meaning this.foobar is equal to window.foobar
When you do new while calling a function such as var newfoo = new foo()
function foo() {
this.foobar;
}
this has suddenly become a reference to newfoo. Meaning this.foobar is equal to newfoo.foobar This allows you to make objects that don't need a reference to the actual local variable newfoo
in your case self is just the name of an constant.
To me MakeStuff is just a function, not a constructor. And self doesn't have anything to do with this in the code you provided. Here it's just a variable inside the function that gets assigned some keys and elements param1 and param2.
const MakeStuff = function(param1, param2) {
const returnedElement = {};
returnedElement ._param1 = param1;
returnedElement ._param2 = param2;
// and so on...
return returnedElement ;
}
const someStuff = MakeStuff(param1, param2);
Sometimes you will need to use self (some use that) to access this but within another scope.
A great explanation you can find on another SO thread is:
var self = this;
[This is] keeping a reference to the current object, so later when you call [self] you're calling that method on that object, not any other.

Javascript "this" scope giving different result depending on the way it is called

All,
This is the code:
var Person = function (name) {
this.name = name;
this.printName = function(){
console.log("My name is " + this.name);
}
};
var p = new Person("Steve");
var funcRef = p["printName"];
p.printName();//Works
p["printName"]();//Works
funcRef();//returns incorrect value
Find a working example here: http://plnkr.co/edit/57LS6oXPfqccAWf6uqQV?p=preview
My question is what's the difference between the last two? I'm accessing the object method in the same way, the only difference is the way it's being called.
Why does it return a difference result?
First time I have come across this in javascript. I understand it's in a difference scope but i don't know how it got decoupled from the object which is what I'd like to understand.
Thanks
Steve
javascript bind the this keyword when you call the function on the object directly.
With test.fn(), this will be test inside fn. Same with test['fn'](). But if you do var fn = test.fn; fn(), this will be the global root (window in a browser) inside fn.
You can force the this inside a function like this : var fn = test.fn.bind(test);
More informations here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
Case1 :
'this' always takes the context of the object with respect to which its called.
In p.printName() the context is p therefore 'this' references the Person object that 'p' refers to.
Case2:
But, when you direct 'funcRef' to p's method it loses this context and 'this' references the global object.
The global object can be different depending on your js environment (like the browser context or node and so on).
That is why you see different results.
As other answer say, this is bound when you call the function. A common way to keep the reference to the object is to use something like this:
var Person = function (name) {
var self = this; // Keep a reference to this object for later use
self.name = name;
self.printName = function(){
console.log("My name is " + self.name);
}
};
How this scope behaves is already explained by above answers, here is best practice for 'this' usages, use 'this' as a new variable called 'self', see below code, this way you have better control and less error due to wrong usages of this scope.
var Person = function (name) {
var self=this;
self.name = name;
self.printName = function(){
console.log("My name is " + self.name);
}
};

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

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.

Can I get an unbound function from a bound function in JavaScript?

I'm getting my head wrapped about currying and other techniques using Function.prototype.bind.
It seems extremely useful to change function scope (i.e., this value) in certain situations.
However it looks like you can't change the scope with bind once you already did so:
function f = obj.method.bind(42);
function g = obj.method.bind('Hi');
function f2 = f.bind('Hi'); // “this” is still 42
Is it possible to retrieve the original unbound function from a bound function at all?
What the bind method basically does is something like (not exactly, because arguments are sliced to exclude the context):
function bind(context) {
var self = this;
return function() {
self.apply(context, arguments);
}
}
So basically it's returning another function which will call itself with the given context and arguments. If you then bind it again, you'll be binding this newly created function, which will be as if bind was implemented like:
function bind(context) {
var self = this;
return function() {
self.apply(context, arguments);
}.bind(otherContext);
}
But because the inner function returned by bind acts as a closure where the original context is the one binded first (self), that one will be the context in with your function will be really executed.
I thought it would be useful to illustrate Win32's answer with a picture.
A wrapper generated by bind makes sure your function is called with given context no matter what.
Such wrapper will always ignore its own context.
Given a chain of wrappers, any context but the innermost is lost.
Therefore, there is no way to change the context once it has been set using bind.
This would actually solve you issue
const bind = Function.prototype.bind;
Object.defineProperty(Function.prototype, 'bind', {
value: function () {
const result = bind.apply(this, arguments);
result.source = (this.source || this);
return result;
}
});
Now you can get the source property to get the original function.
This could cause other issues, but performance does not seem to be one of them, https://jsperf.com/bind-override/1
Both IE, Edge, Firefox and Chrome seems to get the same result, sometimes the normal version is faster and sometimes the overridden is faster.

Categories

Resources