JavaScript "this" in a function block - javascript

this refers to the object it belongs to, for example:
var someObj = {
logObj : function() { return this }
}
obj.logObj() => someObj
and a function is an object. But then why does this in a function refer to the window, not the function? For example,
function someFunc() { return this }
won't return someFunc(), but window.

It's true, a function is an object. However, the statements inside the function are not called with this set to the function itself. That would keep this from referencing the object that it was called on, and therefore eliminate much of the usefulness of this. There are ways to accomplish what you seek though.
"When a function is called as a method of an object, the object is passed to the function as its this value." ECMAScript Specification 4.3.31
Functions are not called as methods of themselves. Functions not executed as methods of an object are called as methods of the global object (or undefined if in "strict" mode).
function test() {
console.log(this == window);
}
var obj = {'test': test};
test();
window.test();
obj.test();
If you really want for the this in a function to refer to itself, then you will have to add the function as a property of itself, or use a function such as apply, call, or bind which have a thisArg.
function test() { console.log(this) };
test.test = test;
test.test();
test.call(test);
test.apply(test);
test.bind(test)();

Context is most often determined by how a function is invoked. When a function is called as a method of an object, this is set to the object the method is called on:
var obj = {
foo: function(){
alert(this === obj);
}
};
obj.foo(); // true
The same principle applies when invoking a function with the new operator to create an instance of an object. When invoked in this manner, the value of this within the scope of the function will be set to the newly created instance:
function foo(){
alert(this);
}
foo() // window
new foo() // foo
When called as an unbound function, this will default to the global context or window object in the browser. However, if the function is executed in strict mode, the context will default to undefined.

There are at least two ways to create an object - with an object literal, or with an object constructor.
Only when you use the latter technique will this refer to the object it occurs within.
This is how to create an object with an object constructor (in your example, a literal was used) :
var objConstructor = function () {
this.logObj = function () {return this}
}
var obj1 = new objConstructor()

Related

Arrow function and this inside a constructor function

I have read this paragraph about the this keyword : https://bonsaiden.github.io/JavaScript-Garden/#function.this
In this first case this refers to global objet, and it seems totally normal because when we have an arrow function, it automatically bind this with the one in the outer scope.
var obj = {
foo : () => console.log(this)
}
console.log(obj);
obj.foo()
However, I'm not able to explain the following behavior :
function bar(){
this.foo = () => console.log(this)
}
var obj = new bar()
console.log(obj);
obj.foo()
Now, this refers to obj instead of global. Why is that ? It seems to me that using the new keyword with the constructor function should return an object obj which is exactly identical as the one in the first example. And so the arrow function should have a this which refers to global and not to obj. Could you explain to me what's happening in the second case please ?
Functions -> No separate this
Until arrow functions, every new function defined its own this value (a new object in the case of a constructor, undefined in strict mode function calls, the base object if the function is called as an "object method", etc.). This proved to be less than ideal with an object-oriented style of programming
Read more about the new keyword here
The constructor function ... is called with the specified arguments, and with this bound to the newly created object.
The bar() constructor defines this as itself.
Although I myself am far from good with objects (need to work on that), I think that when you do const test = new Test() you initialize a new object. That way, the scope(?) of this references only to the newly created object, thus why you do this.foo and later on you reference to that foo property by using obj.foo. On the other hand, when you just do const obj = { .... }, you don't actually initialize a new object, so the this goes straight to the global object - the window. So, const test = new Test creates a new object, while using only const obj = {} is not a new object and this by default goes to the window object.

Javascript - Call function within object's method bind 'this' to global object

All the articles and books I read say that it doesn't matter where I define my function, it's where I invoke the function that decides which object 'this' is bound to. But with this example, I don't understand why 'this' is bound to global object.
function foo(){
console.log(this);
}
var obj = {
myMethod: function() {
foo();
}
};
obj.myMethod();
As I understand, 'obj' object is the one that invokes the function so 'this' should be bound to 'obj', but the result is window object. Can anyone please explain this for me?
this is a strange beast in JavaScript, so you'd do well to read the overview on MDN.
But in summary, it doesn't matter where the function was originally defined, but what does matter is the location from which it's being executed...
If the function is defined globally and you invoke it using myFunction(x), then it's executing in the global scope, and this will refer to the global object (as you have discovered in your foo() function where this is the Window object)
If a function is contained in an object's property then this will refer to the object that contains the property. (Object properties which contain functions are called "methods")
For example...
myFunction = function() { console.log(this); }
myObject = {
myMethod: myFunction
}
myFunction(x) // `this` == the global window object.
myObject.myMethod(x) // `this` == `myObject`
NOTE 1. You can also invoke functions using 'call', 'apply', and 'bind'
which enable you to specify what this should refer to inside the function when it runs. (Read about them in detail on the link I provided.)
NOTE 2. The ES6 "arrow function" syntax ((x)=>{ ... }) is an exception, as this will always be the same value as this would be wherever the arrow function itself was defined.
When foo() is created it is created with a closure . When it is invoked it still remembers its scope through this closure with which it was created and at that time, this was bound to global object.
You're calling foo from within myMethod, so it isn't obj directly calling foo. To have this point to obj you should assign foo directly to myMethod.
e.g.
function foo() {
console.log(this);
}
var obj = {
myMethod: foo
};
obj.myMethod();

why call.call invokes function

Here if I have a function which logs "called my function"
function myFunction() {
console.log('called my function')
}
Function.prototype.call.call(myFunction) // => "called my function"
while during a single call like:
function myFunction() {
console.log('called my function')
}
Function.prototype.call(myFunction)
When you write someFunction.call(foo), it means to call someFunction while passing foo as the this parameter. Normally you have someObject.someFunction(), which passes someObject as this implicitly, but with .call you can set this to anything you want. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call.
So what does Function.prototype.call(myFunction) do? Well, it calls Function.prototype, passing myFunction as this. What does calling Function.prototype do? According to the ECMA specification:
The Function prototype object is itself a Function object (its [[Class]] is "Function") that, when invoked, accepts any arguments and returns undefined.
That's why Function.prototype.call(myFunction) has no visible effect.
On the other hand, Function.prototype.call.call(myFunction) calls Function.prototype.call (which is itself a function!), passing myFunction as this. What does this do? Exactly the same as myFunction.call(): When you look up the call property of a function object, you get it from Function.prototype anyway (through object inheritance). So what does this do? It calls myFunction with no (normal) arguments, but the value of this it sees is a bit tricky: If the function is in strict mode, this will be undefined; if it is non-strict, this will be the global object (a.k.a. window in browsers).
This is also the same behavior you get from myFunction() (i.e. not calling it on an object). In other words, Function.prototype.call.call(foo) is just a (very) roundabout way of writing foo().
In short, call itself does not expect a function as an argument and will not invoke it's argument as a function: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
Rather, call is member function of all Function objects defined in their prototype which enables you to invoke a specific implementation of a member function while passing the argument to be used as this in the function invocation. Since call itself is a Function, it too has a call member function.
One use case of this is emulation of the super concept in e.g. Java. Consider another example with a function other than call:
function Foo() {
console.log('Foo');
}
Foo.prototype.bar = function () {
console.log('Foo bar');
};
function Baz() {
console.log('Baz');
}
Baz.prototype = Object.create(Foo.prototype);
Baz.prototype.bar = function () {
Foo.prototype.bar.call(this);
// Call the super class implementation of `bar`
console.log('Baz bar');
};
var baz = new Baz();
baz.bar();
A little context:
call is a function that belongs to the Function object, as you probably know.
So if we have this function: (note the this)
function invite(where) {
alert ("hi "+this.name+" do you want come to "+where);
}
and this object:
var obj = { name:"PETER" }
we could do
invite.call(obj, "the cinema")
The first parameter to call is the CONTEXT. The function will be executed within the context of that object, that's why the alert will display "PETER" for this.name
The second parameters and so on are the parameters, that's why the alert will display "the cinema".
The second case: Function.prototype.call.call
Function.prototype.call is the raw "call" function of the function object. So you are accessing this function directly, and want to call it for your object ("call the function call"):
Function.prototype.call.call
You want the function "call" to be called within the context of your function myFunction (first call paramerer):
Function.prototype.call.call(myFunction, ...);
That is, in fact, equivalent to
nyFunction.call(...);
The first case
The first case does nothing because prototype is itself a function (that you can ".call" :) , so
Function.prototype.call(whatever)
would just be equivalent to
Function.prototype();
executed in the context of your function

Do not modify context even using a function that modifies the context

Maybe the title sounds a little bit weird (please improve it) -- but I need a solution for the following scenario. I have the following code:
var Foo = function () {
this._hello = "world!";
};
Foo.prototype.bar = function () {
console.log(this._hello);
};
var f = new Foo();
f.bar(); // => "world!"
f.bar.apply(this); // => undefined
I know that apply changes the context, so inside of bar, this will be the global object (at the second call).
But what I need is to access this from Foo function. A solution that I see would be:
var Foo = function () {
var self = this;
self._hello = "world!";
self.bar = function () {
console.log(self._hello);
};
};
However, I would choose not to have method declarations inside of another function.
I'd prefer to define methods same column level (just for code style):
var Foo = ...;
Foo.prototype.method = ...;
Is this possible? How?
You can use the bind() method to tackle these kinds of problems. Instead of something.method(f.bar) call something.method(f.bar.bind(f)) to get the bar method always called on the expected context (f).
If you don't want to use bind in every location where you pass bar around as a callback, you can also put it in the constructor to create a dedicated bound function for every instance by default:
function Foo() {
this._hello = "world!";
this.bar = this.bar.bind(this);
}
Foo.prototype.bar = function () {
console.log(this._hello);
};
var f = new Foo;
something.method(f.bar); // works!
It's not possible to do this by assigning a function to the prototype like this.
Unless you assign something to f.bar directly (as in your second example, and Bergi's answer), the value you will get for f.bar is a reference to the function you assigned to the prototype's property Foo.prototype.bar. This will be exactly the same function object for any other object that has Foo.prototype as a prototype. There is no reference to f in this function object.
So when you call f.bar(), how does this refer to the value of f? It is a special syntax, that basically equates to f.bar.apply(f). It is only the fact that you use this method-call syntax that sets this to the value of f. Any other reference to f.bar will just evaluate to the prototype's single, shared function object.
If you call it with f.bar.apply(somethingElse), this is now set to somethingElse, and all association with f is lost.
It's not a question of apply(...) changing scope. fn.apply(x) sets this to x within fn, whereas y.fn() sets this to y.
Similarly, in your example if you assign f.bar to a variable and then invoke it via the variable instead of using the method-call syntax f.bar(), your this will be the window object (if running in a browser) and again you'll get undefined.
var func=f.bar; // now func === Foo.prototype.bar
func(); // => undefined
See also How to find the object a function belongs to?

this inside function

My question is:
function Foo()
{
this.foo = "bar"; // <- What is "this" here?
}
From what I can tell it depends on how Foo is used, i.e. as a constructor or as a function. What can this be in different circumstances?
The this keyword refers to the object the function belongs to, or the window object if the function belongs to no object.
It's used in OOP code, to refer to the class/object the function belongs to
For example:
function foo() {
this.value = 'Hello, world';
this.bar = function() {
alert(this.value);
}
}
var inst = new foo();
inst.bar();
This alerts: Hello, world
You can manipulate which object this refers to by using the apply() or call() functions. (A very very handy feature at times)
var bar1 = new function() {
this.value = '#1';
}
var bar2 = new function() {
this.value = '#2';
}
function foo() {
alert(this.value);
}
foo.call(bar1); // Output: #1
foo.apply(bar2, []); // Output: #2
Read what Douglas Crockford has to say on the matter, to quote him from A Survey of the JavaScript Programming Language:
A function is an object. It can contain members just as other objects. This allows a function to contain its own data tables. It also allows an object to act as a class, containing a constructor and a set of related methods.
A function can be a member of an object. When a function is a member of an object, it is called a method. There is a special variable, called this that is set to the object when a method of the object is called.
For example, in the expression foo.bar(), the this variable is set to the object foo as a sort of extra argument for the function bar. The function bar can then refer to this to access the object of interest.
In a deeper expression like do.re.mi.fa(), the this variable is set to the object do.re.mi, not to the object do. In a simple function call, this is set to the Global Object (aka window), which is not very useful. The correct behavior should have been to preserve the current value of this, particularly when calling inner functions.
Also 'this' can change depending on how your function is invoked, read on apply function and call function.
I would recommend that you spend time learning form one of JavaScript's greatest minds in his (free) presentations, linked from here.
In JavaScript, the convention (and this is only a convention) is that any function that begins with a capital letter is to be used as a constructor. Then, one would call
var foo = new Foo() and this would refer to the newly created object that is about to be referenced by foo.
Of course, there is nothing stopping you from calling Foo() on its own, in which case this would then refer to the object from which the function was called. To avoid confusion, that is not recommended.
Its depends on how that function is used, there are two basic types in which we can use functions
Function
Function as an Object, by using new keyword
will see one by one
1.Function
var example = function () {
console.log(this);
};
example();
Output : window
Here 'this' keyword points to window object.
By default, this should always be the window Object, which refers to the root - the global scope. So when we console.log(this); from our function, as it’s invoked by the window (simply just called), we should expect the this value to be our window Object:
2.Function as an Object
var example = function () {
console.log(this);
};
var obj = new example();
Output : example {}
Here 'this' keyword points to newly created example object.
In NodeJS there is some interesting behaviour:
function foo() {
this.name = 'bar' // <- What is "this" here?
}
foo() // <- TypeError: Cannot set property 'name' of undefined
But using an arrow function:
const bar = () => {
this.name = 'foo'
console.log(this)
}
bar() // <- { name: 'foo' }
I was always under the impression that a traditional function literal had its own context but not arrow functions, this seems to contradict my understanding.
Given this behaviour the code by the OP would not work...
In JavaScript everything is object even functions. When you say this.foo in following code
function Foo()
{
this.foo = "bar"; // <- What is "this" here?
}
foo becomes member variable of Foo object

Categories