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

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();

Related

Using This in Javascript

I have read over some rules to determine what the value of this is in different scenarios in Javascript. All was well till the example below threw me off.
function Person(name){
this.name = name; //this is the object when function used as constructor (as expected)
this.changeName = someFunction(); // produces error
function someFunction(){
this.nickName = this.name+"by"; //this is now the global object and not the instance, thus the name property does not exist.
}
}
var a = new Person ('bob'); //error due to the function in changeName property.
From what I understood, the this variable takes up the value of the invoking object when called through dot notation or takes up the value of the newly constructed function when used with the new key word.
Can someone explain why the this statement in the function above is the global objet and not the newly instantiated object?
Can someone explain why the this statement in the function above is the global objet and not the newly instantiated object?
Because when you call a(n unbound) function as func(), this will refer to the global object (or undefined if the function is in strict mode).
Every function (except arrow functions) has its own this value. So the fact that you are calling Person as new Person() and that this inside Person refers to a new object, doesn't have any impact on the this value in someFunction. It only matters how you can someFunction.
You could call someFunction and explicitly set its this value via .call:
this.changeName = someFunction.call(this);
See also: How to access the correct `this` inside a callback?
The this within someFunction() will reference a global object, because it's inside a function call. See a fuller, much more complete explanation at How does "this" keyword work within a function?
If you wish to solve the issue, alias this inside the parent.
function Person(name){
var self = this; // Store a reference to the current instance
self.name = name;
self.changeName = someFunction(); // Odd that you'd capture the return value of a setter, ...
function someFunction(){
self.nickName = self.name+"by"; //self references the instance, creating the property.
}
}

JavaScript "this" in a function block

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()

'this' in a function VS 'this' in a method

From Javascript-Garden:
Foo.method = function() {
function test() {
//this is set to the global object
}
test();
}
In order to gain access to Foo from within test, it is necessary to create a local variable inside of method that refers to Foo:
Foo.method = function() {
var that = this;
function test(){
//Use that instead of this here
}
test();
}
Could anyone explain this? As far as I understood, this refers to the global object if it's called in the global scope. But here it's called inside of a function, which is inside a method (first example). Why exactly does it refer to the global object, while the second example doesn't?
As far as I understood, this refers to the global object if it's called in the global scope.
No. this will refer to the default object if the function is called without explicit context. The scope is irrelevant. (In strict mode it will refer to undefined instead).
Why exactly does it refer to the global object
We can't tell what it refers to. The value of this is determined by how the function is called, not how it is defined.
Now you have updated the example, we can see that it is called without context, so this (in the inner function) will be the default object, which in a web browser is window (it would be undefined in strict mode).
while the second example doesn't?
In the second example, the inner function doesn't use this (which will have the same value as the previous example).
The second example uses that instead. that is defined in the scope of the outer function and is set to whatever the value of this is when that function is called.
Assuming that function is called as Foo.method() then (outer) this (and hence that) will be Foo because that is the context on which method was called.
this in a function isn't set when you define the function. It's only dynamically defined to the receiver of the function call.
If you call foo.test(), this in test will be foo.
But if you do
var f = foo.test;
f();
then this in f (which is foo.test) will be the external object (window if you're executing it at the root level).
It would be the same with
foo.test.call(window);
The second example uses a closure to place the outer functions variables on the scope chain of the inner function.
Foo.method = function() {
var that = this;
function test(){
//This function has access to the outer variables scope chain.
}
}

What's the scope of an item in an JavaScript Array

I'm playing around with scopes in JavaScript and I was curious about something I ran across when calling a function from an array. In the below example I work with three different scopes. One bound to an Object called foobar, one bound to window and then a third one which actually refers to the function itself. I'm just curious why the function is scoped to itself and not to the global window object. Is it because Array access is a function call itself so the stored function is in a local scope?
var foobar = {
doWork: function() {
console.log('doing some work...');
console.log(this);
}
}
foobar.doWork(); // `this` will refer to foobar
var doWorkClone = foobar.doWork;
doWorkClone(); // `this` will refer to window
var workClones = [];
workClones.push(foobar.doWork);
workClones[0](); // `this` will refer to the doWork function itself
They behave the same way. In a.b(), the function a.b is called with this set to a.
foobar.doWork(); // function is `foobar.doWork`, `this` is `foobar`
workClones[0](); // function is `workClones[0]`, `this` is `workClones`
This is because the . and [] notation are functionally the same thing. It does not matter which one you use, nor does it matter whether you're dealing with an array or not.
to understand this, litteraly, it might be helpfull to see how the js works under the hood.
when you write f(args), js will execute f.call(this, args). Hence this always refers to where you call the function from.
In your case:
foobar.doWork() --> foobar
doWorkClone() --> window or wrapping expression
workClones[0]() --> "0" is in workClones, so workClones

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