What is the meaning of this.foo()? - javascript

I understand the concept of using this to assign values to a variable:
this.foo = 37;
But I am confused about using it in connection with a function invocation:
this.foo();
What is the meaning of this?

This is just the context of how a function was called. In the global execution context (outside of a function) its the global object. In your case this is just some type of object that foo is a property on it. The property can be a value like an integer or even function.
var someObject = {
foo1: 37,
foo2: function () {
return this.foo1;
}
};
someObject.foo2.apply(someObject);
In the example above I created an object with two properties. One is an integer value and the other is a function. Then I call the function on the object using apply which allows us to set the context of the function. I set the context as the object I created so once inside the function I can reference it as this.

Functions in JavaScript are first class objects. They can be treated like any other object.
They can be stored in variables. They can be stored in properties on other objects. They can be passed around as function arguments.
This is just an example of a property whose value is a function.
var obj = {};
obj.foo = myFunction;
obj.foo();
function myFunction () {
document.body.style.background = "red";
}

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

Calling a constructor function | why does "this" keyword return undefined?

I'm playing around with objects and constructors and am curious why I can't execute: person(5,10). The parameters are passed to the person function but then the variable assignment disappears and I get the "cannot set property "age" of undefined" error in chrome.
"use strict"
function person(age, height){
this.age = age;
this.height = height;
this.calculate = function(){
var newHeight = this.height * 2;
console.log(newHeight);
}
}
person(5,10);
The confusion comes because a function can be used as a callable function and an object constructor both.
Good practice is to not mix up both forms, meaning a constructor function should not be used as a callable function.
In general constructor function has first letter capitalized (just by convention to give a hint to the reader of the code).
Object based languages in general implicitly provide the reference to the object on which a method is called. In Javascript this reference is "this" keyword inside the function.
Consider the following code.
var obj = {
sum: 0,
add: function(increment) {
this.sum += increment;
return this.sum;
}
};
When we call obj.add(2), interpreter or compiler in any other object based language will do an internal calling of method add as following
add(arguments..., [this=obj]) {
//this is the obj reference inside the method
}
add(arguments, obj);
Above is just a pseudo code, last parameter is hidden from us and we don't need to pass it explicitly, this parameter is the reference to the actual object on which the add() method was invoked and is available via "this" keyworkd.
In general when we declare a function outside an Object scope, it becomes method (Edited** if not nested in another function) of the global object ( normally window object). So it's invokation will pass global object as the "this" reference. In strict mode default global object is undefined and any operations that have to be done on the window or global object are to be done explicitly. So that we do not modify the global object inadvertently.
When we call a function as a constructor like below
var p1 = new Person();
Interpreter will execute a code similar to
var newObj = new Object();
Person(arguments..., [this=newObj]) {
//this is the newObj reference inside the method
return this;
}
Person(arugments..., newObj);
I hope it's a bit clearer now.
I get the "cannot set property "age" of undefined" error in chrome.
When you call a function in strict mode, this is undefined. It seems you want to call the function as constructor, with new:
new person(5, 10)
Learn more about constructors.
Note: The convention is to capitalize the name of constructor functions.

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