javascript "this" points to Window object again - javascript

I asked a question on Javascript this points to Window object regarding "this" points to Window object.
here is source code
var archive = function(){}
archive.prototype.action = {
test: function(callback){
callback();
},
test2: function(){
console.log(this);
}
}
var oArchive = new archive();
oArchive.action.test(oArchive.action.test2);
Tim Down wrote "but that function is then called using callback(), which means it is not called as a method and hence this is the global object".
What are differences between calling a function by its actual name and callback() as shown on the source code?
How does console.log(this) in test2 points to Window when it is inside archive.action???

In JavaScript you can invoke functions using 4 different invocation patterns:
Function invocation
Method invocation
Apply/Call invocation
Construction invocation
The patterns mainly differ in how the this parameter is initialized.
When you use oArchive.action.test2(), you would be invoking the test2() function with the method pattern, and in this case this would be bound to the action object. JavaScript will use the method pattern whenever the invocation expression contains a refinement (i.e. the . dot expression or the [subscript] expression).
On the other hand, when a function is not the property of an object, then it is invoked using the function pattern. In this case, the this parameter is bound to the global object, and in fact this is how JavaScript is invoking your callback() function.
Douglas Crockford in his Good Parts book, describes this as a mistake in the design of the language, and suggests some possible workarounds. In you case, one easy workaround would be to invoke the callback using call() or apply(), as Tim Down suggested in your previous question:
callback.call(this);
This works because the Apply/Call invocation pattern lets you choose the value of this, which is what you require.

In javascript the this keyword is set to the owner of a function. Function objects do not maintain their ownership themselves, instead the ownership is deduced from the way we call a function.
eg:
var foo = function() {
alert('hello');
};
var abc = {};
abc.bar = foo;
Simply calling the function like
foo();
gives the interpreter no clue about what object the function might be attached to. It may be attached to multiple objects, it may be a variable etc. So the interpreter sets this to the global object.
But however, when calling a function like
abc.bar();
the interpreter knows that function is attached to abc object, therefore this is set to abc. Even if both bar and foo refer to the same function object, the difference in the calling pattern causes this to behave differently.

Related

Javascript event listener works with arrow function, not with normal function [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.

Cannot "reach" class properties from inside method [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.

function vs method in JavaScript

In this example below is onlaod a function or a method? I would assume this is a method as that is associated with the img object.
Can anyone clarify this?
img.onload = function () {
ctx.drawImage(img, 10, 10);
ctx.drawImage(img, 170, 90);
ctx.drawImage(img, 170, 170);
};
Many thanks,
P
A "method" in JavaScript is just a property on an object that refers to a function. From the specification:
method
function that is the value of a property
So in that sense, what you've shown is both a "method" and a "function."
In another sense, if you define "method" as "a function tied exclusively to a given object or class of objects," JavaScript doesn't really have methods at all (but keep reading). (More about that on my blog: Mythical methods.)
For instance, you could consider slice a method of Array objects, but it can be used on any other object you like (as long as that object is array-like, since otherwise slice doesn't know what to do):
var o = {
0: "zero",
1: "one",
2: "two",
length: 3,
slice: Array.prototype.slice
};
console.log(o.slice(1));
That said, some functions will fail with an error if they're called with this not referring to the kind of object they expect (for instance, Number#toString), which in some sense makes them true methods.
In any case, it's very common indeed to use the term "method" to refer to a property that refers to a function. In fact, the specification does it when talking about things like this:
// ES2015+
let obj = {
method() {
}
};
and this:
// ES2015+
class Foo {
method() {
}
}
Methods are properties that are type Function
Without formal language specific definition one should alway defer to the common usage implicit meaning.
In computer programing;
A method is a function that is a part of a class, it may or may not return a value.
A function is set of statements that returns a value.
A procedure is a set of statements that do not return a value.
But if there is a language scoped formally explicitly defined meaning one should use it.
Javascript's function and method
Javascript "ECMAScript 6" formally defines the term Function as.
...and a function is a callable object.
and Method as
A function that is associated with an object via a property is called a method.
Reference ecma-262 7.0, Ecmascript Overview
Which sucks as I have always used function and now have to emend all my documents to the correct term.
Contradiction
It also creates contradiction in regard to the lexical syntax used to describe and document javascript code.
All callable functions/methods are Function objects and have the Function.prototype. In the strict sense there are only functions when describing what a variable is referencing (or anonymously).
For example consider
var poo = function(){}; // Method window.poo, function poo.
function Foo(){ // this is a function?
var tic = function(){}; // tic is a function
this.Bar = function(){ // this is a function as well as a method
this.poo = poo; // This is a method, it is also function
}
this.Boo = function(){
this.poo = function(){ return poo}; // anon function returns the poo
// to create the method Boo.poo
}
}
Top is a function as it is a callable object. but it is also a property of the top scope window (or context top level scope), and is thus a method of window.
Thus as defined by the Javascript standard Foo, Bar, and Boo are functions and at the same time methods. This ambiguity in programing can be a problem that could lead to bugs, or worse design reviews if pedantic programmers like me are forced adhere to the design spec.
Suggested lexical usage of "method" and "function"
Personally I will opt to the following useage of the words function, and method.
All callable statement lists are functions, that is their type.
I will call them functions unless I referance the object they are a property of.
I will call them a method when I referance without ambiguity the object they are a property of.
If documenting with scope including JavaScript implementation language (usually c++) I will call internal (hidden from Javascript's context) callable code as methods or functions depending on if they return a value or not
From above code.
Foo, Bar, Boo, and poo are functions
Foo is a method of window.
Bar is Foo's method.
Bar's method poo does nothing
Boo.poo is a method.
poo is a function, that is its type.
poo is a function common to both window, Bar and Boo *
'tic' is a function
There is no method named tic.
The method Bar.poo is declared in the function Bar
The method Bar.poo is defined as an anonymous function
The method Bar.poo is a referance to a function
The method. Boo.poo is a referance to the method window.poo
*as there is ambiguity to the object that poo is a property of, refer to it as a function
The referance to the object that methods belong to can be a contextually explicitly reference.
CanvasRenderingContext2D is an object used to render to the canvas , drawImage and clearRect are 2 of its methods.
Or contextually implicitly referred
After getting the context from the canvas, the methods drawImage and fillRect can be used to overwrite all pixels.
Getters and setters are functions. They are methods of the object they are a property of but should only be called functions when referring to the declaration and defining statement list. Or as simply properties of the object. Calling them methods implies the function calling syntax name()
Anonymous functions can not be methods as they can not be accessed via a named property.
To answer the OP
onload is a property of Image. It is never a function or a method of Image
The object of type Image will have the method onload if defined, called when image has loaded. If the method onload is not defined then nothing will happen when the image has loaded.
img.onload is a method. Or onload is a method of img. True only after it has been assigned a function
drawImage is a function, that is its type.
ctx.drawImage is a method.
drawImage is ctx's method,and it is a method of CanvasRenderingContext2D
I would tend to say every function in Javascript is a method. But I'm not sure if this is justified. Please correct me if I'm wrong.
So, a method has a "this", that is the object that was affected.
In your example this = img
img.onload = function () {
console.log(this);
...
}
Well, any function has "window" as "this", unless it has something else as this.

Nested functions & the "this" keyword in JavaScript

"The this keyword always refers to the object that the containing function is a method of."
Great, sounds simple enough, but here's what I'm wondering about...
For example:
function func1() {
function func2() {
alert(this == window); // true
}
func2();
alert(this == window); // true
}
func1.func3 = function () {
alert(this == window); // false
alert(this == func1); // true
};
func1();
func1.func3();
Now, since func1 is actually a method of the global (window) object (a function object assigned to the property func1 of the global object) it makes sense that this inside func1 refers to the global object, and since func3 is a method of func1's function object it makes sense that this inside func3 refers to func1's function object.
The thing that bothers me is func2. I know that this inside a nested function is also supposed to reference the global object, but I'm not sure why since func2 is NOT a method of the global object. As far as I understand (and this is the part I might be completely wrong about) func2 is a method of func1's call (activation / variable) object. Now, if I'm right about this (and I'm not sure that I am) then shouldn't this inside func2 refer to func1's call object instead of the global object?
So, I guess my question would be: Is a nested function a method of the call (activation) object of the function it is nested in, and if so, shouldn't this refer to that call object instead the global object?
The this keyword always refers to the object that the containing function is a method of.
No. Unfortunately, it is not easy as that. The documentation of the this keyword at MDN gives a good overview. It is set to the object when the function is called as a method on it, but there are other possibilies. The default is that this is undefined when it is called without anything special, like you do with func1 and func2. For sloppy (non-strict) mode functions undefined (and null) are not used though, this does point to the global object (window in browsers) for them in that case - what you are observing.
But it could also point to fresh object instances when the function is called as a constructor (with the new keyword), or to an event target (like a DOM element) when used as a handler. Last, but not least, it could be set manually with call, apply or bind…
this has nothing to do with nesting. Nesting function declarations/expressions only affects the scope ("privacy", availability) of variables. While the variable scope of a function never changes, the value of this can be different on every invocation - it is more like an extra argument.
The meaning of the this keyword inside a function depends on the way the function is invoked. There are 4 different function invocation patterns in JavaScript.
function invocation pattern foo()
method invocation pattern o.foo()
constructor invocation pattern new foo
call/apply pattern foo.apply(...) or foo.call(...)
Only in #2 is it the case that this inside the function refers to the object of which the function is a method.
You are invoking func2() with the function invocation pattern. When doing so, this refers to the global object.
As suggested by #Bergi, see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this for more detail on the meaning of this and the different function invocation patterns.
but I'm not sure why since func2 is NOT a method of the global object.
Any thing defined inside a function is local to the scope of that function. So func2 belongs to the local scope of func1 and therefore is not attached to window.
In Javascript, the value of this is generally based on how you call the function. When you call a function without any leading object, this is usually set to the global parent object, which is window.
You can explicitly set the value of this in three ways:
myObj.func(a, b); //this set to myObj implicitly because myObj is the parent
func.call(myObj, a, b); //this set to myObj explicitly; the first argument
//to call sets the value of this for that function
func.apply(myObj, [a, b]); //this set to myObj explicitly; the first argument
//to apply also sets the value of this for that
//function.
this can be a tricky concept. MDN has a good article about this.

Finding the parent object of a callback function

I have a function:
myObject.myFunction = function(callback){
callback();
}
and a callback
randomObject.callBack = function(){
console.log(this);
}
if I call randomObject.callBack() directly, I get the parent object in the console. However, if I call myObject.myFunction(randomObject.callBack), it logs a DOM Element.
How can I access the parent object?
Note
I do not know the name of the callbacks parent object ahead of runtime.
The context (i.e. this value) of an object is determined at the time the function is run, not at the time it is defined. Passing randomObject.callBack to another function does not send the context (the randomObject bit); it just sends the function.
Presumably the context is set when myFunction calls it. Since you aren't explicitly providing a context (e.g. with call or apply), the context will be the window object.
You can change this by explicitly saying what the context of the function should be before it is run. You can do this with the bind method:
myObject.myFunction(randomObject.callBack.bind(randomObject))
Now when you call callback inside myFunction, randomObject will be logged.
Note that bind is relatively new; not all browsers support it. The MDN page I linked to above has a bit of code that will make it work in all browsers.
This happens because when you invoke a function without an object, inside the function this will point to Window object.To avoid this we usually do like this
myObject.myFunction = function(callback){
callback();
}
randomObject.callBack = function(){
console.log(this);
}
function proxyCallback(){
randomObject.callBack();
}
myObject.myFunction(proxyCallback);
In javascript, this refers to the object context in which a function is called. This is not necessarily related to any object on which it has been defined.
You can think of it as though functions are not defined as members of objects, but called as members of objects.
There are four things that this might resolve to, depending on context.
A newly created object, if the function call was preceded by the new keyword.
The Object to the left of the dot when the function was called.
The Global Object (typically window), if neither of the above are provided.
The first argument provided to a call or apply function.
In your situation, something like this might be appropriate:
myObject.myFunction(function(){randomObject.callBack()});
This creates a closure so that within myFunction, callback is called as a member of randomObject.

Categories