Javascript function and this [duplicate] - javascript

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 8 years ago.
I am learning javascript but I have some doubts about functions/closures, i have this code:
var obj = { value: 0 };
obj.test = function() {
var that = this;
var f1 = function() {
console.log(that);
};
f1();
};
obj.test();
var x = obj.test;
x();
I know that when a function is invoked like f() this refer to the global object but in my example when f1 is defined it has a reference that to the this of the outer function that refer to obj.
I expect that the function remember the context in which it was created so why the last call x() refers to the global object?
Thanks

I expect that the function remember the context in which it was created
That right there is your mistake. JavaScript functions do not "remember" any relationship to any particular object in a case like that. The only things they remember are in-scope variables in the chain of parent lexical contexts. In this case, the "obj" variable is such a variable.
You can explicitly create a function that remembers a relationship to an object with the .bind() method.
obj.boundTest = obj.test.bind(obj);
var x = obj.boundTest;
x(); // will do the right thing
or even more simply:
var x = obj.test.bind(obj);
x();

I expect that the function remember the context in which it was created
It doesn't.
Context is determined by how a function is called and only by how a function is called.
You are calling it in the global context, so this is the global object.

The reason for this occurring is that when you make a copy of that function
var x = obj.test;
you are only copying the function. Not the object, nor any of its variables. So when you attempt to run x (which is obj.test) it runs fresh. The result is that this is re-evaluated which now refers to the global context (or undefined in strict mode).

Related

What is "this" in an arrow function in JavaScript

I have a question about what the "this" points to in an arrow function:
// run this file in nodejs by: node test_this.js
const obj = {
scope:this,
func1:()=>{return this},
func2:function(){
const fn = ()=>this;
return fn();
}
}
console.log("0",obj.scope); // module.exports
console.log("1",obj.func1()); // module.exports
console.log("2",obj.func2()); //obj
const newFunc2 = obj.func2;
console.log("newFunc2",newFunc2()); //global
As I konw, arrow function has no own "this". The scope determines the "this" once the arrow function is declared, and it will never be changed. But why the console.log("2",obj.func2()); outputs the obj? and why console.log("newFunc2",newFunc2()); print a different result global?
The lexical value of this for your obj declaration is module.exports. That's the value of this when your obj variable is declared.
So, that explains why obj.scope is module.exports because that is the value of this at the time your object is declared and initialized with your code scope:this,
As you seem to already know, the arrow function declaration when called with an object as in obj.func1() does not carry through obj as this. Instead, it uses the lexical version of this (what it was at declaration time). As obj.scope shows, that lexical value of this is module.exports. So, the result of console.log("1",obj.func1()) is module.exports as expected (because func1 is defined as an arrow function.
Then, with obj.func2(), that is declared as a normal function so the value of this inside of func2, when called as obj.func2() will be obj. This is how method function calls like obj.func2() work in Javascript (as long as the function is a normal function definition or method definition, not an arrow function).
Lastly, when you do this:
const newFunc2 = obj.func2;
You are getting a reference to JUST the func2 method, all by itself. You've isolated just the method and it has no association at all with the object any more. So, when you call it like this:
console.log("newFunc2",newFunc2());
The object referenced for obj is completely gone and the this value will be set the same as any plain function call will be. The value of this will be set to undefined if you're running strict mode or to the global value if not running strict mode.
For a bit of a review of how all this works or a reference for the future, see:
The 6 ways the value of this is determined inside a function at execution time.
When you're assigning obj.func2 to newFunc2, the function is copied to the new variable, having no connection with the obj anymore. So when you are calling newFunc2(), it's referring to the window object by this in that scope. Below example demonstrate that obj.func2 when defined, doesn't have any information of className. When we copy the function func2 in the class MyObj, this now refers to the new class, hence you get the log this.className = 'MyObj'
const obj = {
scope:this,
func1:()=>{return this},
func2:function(){
const fn = ()=>this;
console.log(this.className)
return fn();
}
}
class MyObj {
constructor() {
this.className = 'MyObj'
this.obj()
}
obj() {
this.func2 = obj.func2
}
print() {
this.func2()
}
}
var myObj = new MyObj()
myObj.print()
.
The JavaScript this keyword refers to the object it belongs to.
It has different values depending on where it is used:
In a method, this refers to the owner object.
Alone, this refers to the global object.
In a function, this refers to the global object.
In a function, in strict mode, this is undefined.
In an event, this refers to the element that received the event.
Methods like call(), and apply() can refer this to any object.
In strict mode, when used alone, this also refers to the Global object [object Window]
"use strict";
var x = this; // x equals [object Window]

Function Context in Javascript and this Keyword [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 6 years ago.
Could somebody here please get this straight for all of us once and for all?
var parent = {child: function(){
console.log(this);
var log = function(){
console.log(this);};
log();
}
}
When I call parent.child()
I get:
Object{}
Window{}
Other people/ documentation on Mozilla say that this function has been invoked without any context. And
this
will be the object on which the function is invoked.
What I don't understand is how on earth this function within another object is considered to be without a context(so this defaulted to the global object). What's the logic here? Thanks
Function referenced at objects are like methods. When you directly call a function by indexing an object, this same object will be referenced by this in the scope the function will generate.
When calling a function without indexing an object, or without setting this context (with apply, bind, call, ...), if it's not at strict mode (or is at least in a global scope when at strict mode) this should be the global object.
When objects are instances of classes/interfaces/functions, their methods also capture this same object for this.
This is how it works for me:
(function() {
'use strict'
console.log(this) // undefined
})()
console.log(this) // Window{}

Can someone explain working of this js code with reference to 'this' keyword?

JS code is:
this.sound1 ="global";
function cat(){
this.sound = 'meawo!!!!';
this.sound1 = 'meawooooo!!!!';
meawo1 = function(){
console.log(this.sound1);
console.log(this);
};
function meawo2(){
console.log(this.sound1);
console.log(this);
};
this.meawo = function(){
console.log(this.sound);
console.log(this);
meawo1();
meawo2();
};
};
var c = new cat();
c.meawo();
Output is:
Question: How come this inside of meawo1(function expression) & meawo2(function expression declaration) is referring to "global" and not to object c? Why is that?
Always remember a simple tip while wanting to know to which object does this refer to.
obj.method();
In the above, method's is called on obj, and hence the this in method will be what it's called on, i.e obj = this.
In your case, though meowo is called on c, meowo1 and meowo2 aren't on the object you want it to refer to.
Functions which don't have an explicit scope from which they are called, default to global context, though the function itself isn't global and can leverage all the variables in its parent context due to a closure.

Understanding JavaScript function declaration syntax [duplicate]

This question already has answers here:
var functionName = function() {} vs function functionName() {}
(41 answers)
Closed 9 years ago.
After using JavaScript for a while, I came up with some questions.
The way to declare a function is:
var myFunction = function(param){//code here}
But there is also another way to declare a function which is
function myFunction(param){//some code}
What's the difference between the two methods to declare a function?
My second question is, I've understood that you can create an object from a function that's declared as:
function Person(name){this.name=name;}
And then, you can have another function declared like this:
function Speak(){console.log(this.name);}
How does the function Speak knows that it's related to the Person Object?
The first one is expression
var myFunction = function(param){//code here}
Second is declaration
function myFunction(param){//some code}
see this article
http://kangax.github.io/nfe/
When u use the word var, your'e declaring a variable realtive to where it's defined, and cannot be accesed from out wheres, and if its inside a function, it's destroyed at the end of the execution, and if you dont use it, you're defining on global ambit, and the variable still exists after the function execution.
The second thing is for programming OOP
Yo can use functions as same as it they were pure objects:
var person = {
name: null,
setName: function (name) {
this.name = name
}
}
Then you can access it's property
person.setName('john');
console.log(person.name);
in the shape of a function
function Person(name){
this.name = null;
}
var john = new Person('John');
console.log(john.name);
When you use this syntax:
function f1(){}
then f1 can be used everywhere in the current scope:
// we can call f1 even before definition of the function
f1(); // it works
function f1(){}
But, When we use this syntax:
var f1 = function(){};
then f1 is like as a pointer to an anonymous function which can be used after the point of assignment:
// we can't call it before assignment of our var
//f1(); // f1 is undefined here!
var f1 = function(){}
// we can call it here
f1(); // works
The second syntax is make more sense when you consider that every function is also an object. for example, we can have a function be a property of an object, like this:
var myObject = new Object();
myObject.say = function(x) {alert(x);};
// myObject now has a property/method named "say"
myObject.say("Hello");
About the second question: the this keyword. can you give the (outer) scope of your code which defines your Person and Speak functions? the code you wrote won't work as it is written. If you want to set proper reference for this in Speak function, you have to write something such as below:
function Person(name){ this.name=name; }
function Speak(){ alert(this.name); }
Person.prototype.DoSpeak = Speak; //here we attach DoSpeak to Speak function
var p = new Person("Saeed");
p.DoSpeak(); //this will work
Both are declaration
1) var myFunction = function(param){//code here}
This is a declaration that is assigned to 'myFunction' local variable
You can set an identifier for that function for debug or recursion purposes
var myFunction = function myFunctionIdentifier(param){ console.log(myFunctionIdentifier.toString())}
But to call this function you have to use 'myFunction ' variable
Another way to perform nested call is by using the arguments.callee that points to the function itself
var myFunction = function(param){ console.log(arguments.callee.toString())}
2) function myFunction(param){//some code}
This is a declaration that is assigned to the scope variable
in case you are in the global area it will be assign (for example in the browser) to the window object
So in fact window["myFunction"]() is valid
* About this question...
function Person(name){this.name=name;}
function Speak(){console.log(this.name);}
The reason that Speak 'knows' Person name is all about JavaScript scope.
Since both using the same scope, both functions 'speak' with the same this.
For example: if you code both functions in the global scope, this == window object thus
console.log(window['name']); will give you the name.
You don't want to code in that way .. since another function using this.name will override you existing logic.
If you will instantiate the Person entity
var person = new Person();
Then person variable will be this, this == person object
And the you can assign Speak in two or more ways:
inline:
function Person() {
...
this.Speak = function ...
}
outside the code, since person assign to (Person)this
person.Speak = function() ...
or the best way, use the prototype object:
Person.prototype.Speak = function() ...

Javascript: why "this" inside the private function refers to the global scope?

Consider the following code:
function A() {}
A.prototype.go = function() {
console.log(this); //A { go=function()}
var f = function() {
console.log(this); //Window
};
f();
}
var a = new A();
a.go();
Why does 'this' inside function 'f' refers to the global scope? Why it is not the scope of function 'A' ?
JavaScript has a different concept of what the special name this refers to
than most other programming languages do. There are exactly five different
ways in which the value of this can be bound in the language.
The Global Scope
this;
When using this in global scope, it will simply refer to the global object.
Calling a Function
foo();
Here, this will again refer to the global object.
ES5 Note: In strict mode, the global case no longer exists.
this will instead have the value of undefined in that case.
Calling a Method
test.foo();
In this example, this will refer to test.
Calling a Constructor
new foo();
A function call that is preceded by the new keyword acts as
a constructor. Inside the function, this will refer
to a newly created Object.
Explicit Setting of this
function foo(a, b, c) {}
var bar = {};
foo.apply(bar, [1, 2, 3]); // array will expand to the below
foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
When using the call or apply methods of Function.prototype, the value of
this inside the called function gets explicitly set to the first argument
of the corresponding function call.
As a result, in the above example the method case does not apply, and this
inside of foo will be set to bar.
Note: this cannot be used to refer to the object inside of an Object
literal. So var obj = {me: this} will not result in me referring to
obj, since this only gets bound by one of the five listed cases.
Common Pitfalls
While most of these cases make sense, the first one is to be considered another
mis-design of the language because it never has any practical use.
Foo.method = function() {
function test() {
// this is set to the global object
}
test();
}
A common misconception is that this inside of test refers to Foo; while in
fact, it does not.
In order to gain access to Foo from within test, it is necessary to create a
local variable inside of method which refers to Foo.
Foo.method = function() {
var that = this;
function test() {
// Use that instead of this here
}
test();
}
that is just a normal variable name, but it is commonly used for the reference to an
outer this. In combination with closures, it can also
be used to pass this values around.
Assigning Methods
Another thing that does not work in JavaScript is function aliasing, which is
assigning a method to a variable.
var test = someObject.methodTest;
test();
Due to the first case, test now acts like a plain function call; therefore,
this inside it will no longer refer to someObject.
While the late binding of this might seem like a bad idea at first, in
fact, it is what makes prototypal inheritance work.
function Foo() {}
Foo.prototype.method = function() {};
function Bar() {}
Bar.prototype = Foo.prototype;
new Bar().method();
When method gets called on a instance of Bar, this will now refer to that
very instance.
Disclaimer: Shamelessy stolen from my own resources at http://bonsaiden.github.com/JavaScript-Garden/#function.this
The reason why is you are invoking f as a function and not a method. When invoked as a function this is set to window during the execution of the target
// Method invocation. Invoking a member (go) of an object (a). Hence
// inside "go" this === a
a.go();
// Function invocation. Invoking a function directly and not as a member
// of an object. Hence inside "f" this === window
f();
// Function invocation.
var example = a.go;
example();
The scope of all functions is window.
To circumvent that, you can do this:
function A() {}
A.prototype.go = function() {
var self = this;
console.log(self); //A { go=function()}
var f = function() {
console.log(self); //A { go=function()}
};
f();
}
Because function f() is not called without any object reference. Try,
f.apply(this);

Categories

Resources