function test1() {
this.name = 'test1';
var that = this;
function test2() {
this.name = 'test2';
console.log(that.name);
}
test2();
}
test1();
When this executes, I expect the console to log out test1. Why do I get test2 instead? I expect the that variable to hold a reference to the test1 function.
Your variable that becomes an object reference since you assign keyword this to it. That means the variable that will be an object and it will have a reference to this(that is, the current object).
Further, the variable that is not a value type. It is an object.
For more on this, search on " value type vs reference types ".
Hope this helps.
In a function definition, this refers to the "owner" of the function.
Please find the description in inline comments.
Rearranging your code according to the order of execution,
test1(); //Now this is called by window object
function test1() {
this.name = 'test1'; //window.name = 'test1';
var that = this; //that is also now window obj
test2(); //this.test2 or window.test2()
function test2() {
this.name = 'test2'; //window.name is now test 2
console.log(that.name); //since in third step, that is window, that.name or window.name is now test 2
}
}
Related
I've a program with functions as Person, greet, specificCall and objects as kumar and chandra.
var fullName=""
function greet() {
console.log("Welcome "+ this.fullName);
}
var Person=function (name) {
this.fullName=name
console.log(this.fullName)
}
var chandra=new Person("chandrakumar")
var kumar=new Person("kumar")
var specificCall=function(){
console.log("Dude "+ this.fullName);
}
var newGreeting=Person.call.bind(specificCall)// I don't understand the meaning here
newGreeting()// logs Dude
newGreeting(kumar)//logs Dude kumar How is this happening
I think Person.call is a function as I have checked typeof Person.call and specificCall is a function again. How can I bind a function to a function?
Though I wrote this code accidentally I don't understand the logic?
Person.call fires the constructor function whereas newGreeting fires the specificCall function. if you look closely newGreeting(kumar) is equivalent to specificCall.apply(kumar). Here the not only context of the scope is changed but the whole function itself. Its like specificCall is bound to Person.call?
Call allows you to set the scope for a functions exection, defaulting to window, while activating it.
//Set global variable to fallback to
var fullname = "Window";
//Set local variable
var person = {
fullname: "Bob"
};
//Definer caller object
function logObject() {
//"this" references current scope
console.log(this.fullname);
}
//Call with nothing, defaulting to global
logObject.call();
//Call with specific object as scope
logObject.call(person);
Bind sets the scope for a function, but doesn't activate it.
//Set global variable to fallback to
var fullname = "Window";
//Set local variable
var person = {
fullname: "Bob"
};
//Definer caller object
function logObject() {
//"this" references current scope
console.log(this.fullname);
}
//Bind with nothing, defaulting to global
var logger1 = logObject.bind();
//Execute
logger1();
//bind with specific object as scope
var logger2 = logObject.bind(person);
//Execute
logger2();
As far as i can tell, you bind specificCall to a call on Person, meaning that firing newGreeting is the same as running Person.call but with specificCall as the bound scope.
It's not pretty code and i would personally recommend a more readable structure:
var fullName = "window";
var Person = function (name) {
this.fullName = name;
};
var chandra = new Person("chandrakumar");
var kumar = new Person("kumar");
function specificCall(scope) {
if (scope === void 0) { scope = window; }
console.log("Dude " + scope.fullName);
}
specificCall(); // logs Dude window
specificCall(kumar); //logs Dude kumar
I wrote the following code, where I would expect the calls to getFull() and useGetFull() to do the same thing, since useGetFull just gets a function object for getFull() and calls it.
function Person(name, family) {
this.name = name;
this.family = family;
}
Person.prototype.getFull = function() {
console.log(this.name + " " + this.family);
};
Person.prototype.useGetFull = function() {
const f = this.getFull;
f();
// f.call(this) works as expected
}
p = new Person("Bob", "Smith");
p.getFull();
p.useGetFull();
However, they don't do the same thing, because inside useGetFull(), "this" is the global object. I noticed that using f.call(this) instead of f() works as intended, but I can't wrap my head around why I have to use it. Why is the value of "this" different depending on how/where I call the function?
A simple rule:
a.b() //b called with context a
d.e() //e called with context d
c() // c called with no context ( so the global instead)
Javascripts context depends on how the function was called.
If you haven't noticed, this.getFull() also works. This is because when you invoke the function as a property of an object (any object), that function's this will refer to that object, the object you invoked the function on, in case of foo.bar(), foo, and in case of this.getFull(), this. This is why this example works as expected:
function Person(name, family) {
this.name = name;
this.family = family;
}
Person.prototype.getFull = function() {
console.log(this.name + " " + this.family);
};
Person.prototype.useGetFull = function() {
/* getFull is preceded by something, it is invoked through "this", so
the "this" reference inside of getFull will be set to the "this" part in
the statement "this.getFull()". */
this.getFull();
}
p = new Person("Bob", "Smith");
p.getFull(); prints out Bob Smith
p.useGetFull(); // prints out Bob Smith
However, when a function is invoked not as the property on an object, in other words, when it is not accessed in a way similar to either foo.bar() or foo["bar"](), but in a way like foo(), even if foo is a reference to a variable whose value is x.y, like f() in your example, its this will be bound to the global object, in a browser, that object is window.
function Person(name, family) {
this.name = name;
this.family = family;
}
Person.prototype.getFull = function() {
console.log(this.name + " " + this.family);
};
Person.prototype.useGetFull = function() {
const f = this.getFull;
/* this call is not preceded by any objects, it is a plain
traditional function call, it is a function invokation in its
simplest form. all functions invoked in this manner will have
their "this" reference set to the global object. */
f();
}
p = new Person("Bob", "Smith");
p.getFull();
p.useGetFull();
If you are interested in this (pun not intended), go here.
What is the difference between the following two JavaScript functions? I know variables declared with var are local inside the function, and if declared withthis` keyword are exposed to outer word. is there any other difference between
function student(param1, param2, param3) {
this.name = param1;
this.age = param2;
this.address = param3;
}
and
function student(param1, param2, param3) {
var name = param1;
var age = param2;
var address = param3;
}
Short answer: You would use the first one for a constructor. The second function does nothing. If you want to use 'private variables', refer to functional scoped variables in the contstructor by instance methods via a closure.
This function would be used the following way to create a student. The parameters passed in are assigned to the newly create student object.
function student(param1, param2, param3){
this.name = param1;
this.age = param2;
this.address = param3;
}
var student1 = new student('steve', 22,'333 E 3rd Ave');
var student2 = new student('rachel', 34,'111 N 1st St');
console.log(student1.name); // 'steve'
console.log(student2.name); // 'rachel'
The second one wouldn't satisfy for a constructor.
It declares variables with functional scope that remain unused. Once the execution of the student function ends, the 3 variables defined within will be garbage collected. This function doesnt seem to accomplish anything.
What do you expect this function to do? It can't be used the same way:
function student(param1, param2, param3){
var name = param1;
var age = param2;
var address = param3;
}
var badStudent = new student('Greg', 22,'222 W 2nd Rd');
console.log(badStudent.name); // undefined
Edit
Someone brought up how to make 'private member variables' using variables declared with var inside a constructor. Use closures:
function student(param1, param2, param3) {
var name = param1;
var age = param2;
var address = param3;
this.getName = function(newName) {
if (newName)
name = newName;
return name;
};
}
var myStudent = new student('steve', 22,'333 E 3rd Ave');
console.log(myStudent.name);
console.log(myStudent.getName());
console.log(myStudent.getName('dan'));
console.log(myStudent.getName());
Note that because the instance method getName refers to a functional scoped variable declared in the constructor, a closure remains that has references those variables. Because of the closure there are still references to the variables once the constructor ends, and they are not garbage collected. Thus via the instance method, you can get and set this variable which cannot be accessed via the resulting object of the constructor.
Basic difference between this. vs var variables is the scope. Variables declared as a part of this will be part of objects and variables declared with var might be private. Might because, it depends on your return. If you do not use return, then they will be private
Sample
function Student(fname, lname, dob) {
var _fname = fname,
_lname = lname,
_dob = new Date(dob);
this.fullName = _fname + " " + _lname;
this.age = (new Date()).getFullYear() - _dob.getFullYear();
}
var stu = new Student('foo', 'bar', '1998/11/13');
console.log(stu);
console.log(stu._fname)
As you see, _fname is passed and was stored using var. So its scope is till function only. So when you try to access it outside function, it is not available.
So in simple, you can use this to define public properties and use var to define private ones.
In JavaScript for creating object we use 'function' as constructor, this constructor functions basically return an object .
when you declare variable with 'var' instants of 'this.var name' , in this case mean you try using those variable to create an object .those variable declared with 'var' just are local variable inside function.
on other hand , when you use 'this.variableName' you create a property for object that constructor function try to create it .
'this.' refer to object that constructor function create.
'var variableName' is just a local variable and it is not a property of 'this' object.
function student(param1,param2,param3){
this.name=param1;
this.age=param2;
this.address=param3;
}
var t=new student('farhad',28,'address');
will create this object:
t{
name:'farhad',
age:28,
address:'address'
}
and
function student2(param1,param2,param3){
var name=param1;
var age=param2;
var address=param3;
}
var t2=new student2('farhad',28,'address');
will create this object:
t2{
}
in 't2' you don't see any property
this is used inside a function and it contains the value of the object that invokes function
Here this refers to the instance of the object & is not assigned a value until an object invokes the function where it is defined
function Student(param1, param2, param3) {
this.name = param1;
this.age = param2;
this.address = param3;
this.print = function() {
console.log(this.name + this.age + this.address)
}
}
var stud = new Student('a', 'b', 'c');
stud.print(); // abc
In the later case var name=param1;var age=param2;var address=param3; you are assigning each of the parameters to a variable and this variables have scope only inside the function
i'm learning about functions. i'm confused in one scenario.
suppose i have three functions
<script>
var fnRef = function() {
console.log("i'm function with no name but refered to fnRef");
};
var funRef2 = function test() {
console.log("im test reffered to funRef2");
};
function test2() {
console.log("i'm test2 named function")
};
</script>
fnRef, fnref2 and test2 will be assigned to window as a property as fnRef and fnRef2 are variable and test2 is named function that act as variable.
but why test2 is not assigned to the global object(window) when refered by funref2? and why i'm not able to execute test(); can someone tell me what is happening in detail.
The named function expression is useful so you can access the function inside it's own scope without using arguments.callee, and it also makes it easier when debugging as the name can be seen in stack traces, breakpoints etc.
This name is then local only to the function bodys scope, meaning
var test1 = function test2() {
if (something) test2(); // available in this scope only
}
test2(); // not here
You can't call the function by it's name, only by the variable it's assigned to, as the functions name is limited to the functions scope when it's a function expression.
When defining a function declaration, the name is assigned to the current scope, and hoisted, so this
var bar = test();
function test() { return 'foo'; }
is more or less turned into this
var test = function() { return 'foo'; }
var bar = test();
Why does self-invocation function inside a function don't get the scope of the outer function in JavaScript?
var prop = "global";
var hash = {
prop: "hash prop",
foo: function(){
console.log(this.prop);
(function bar(){
console.log(this.prop);
})();
}
};
var literal = {
prop: "object"
};
hash.foo();
// hash prop
// global
hash.foo.call(literal);
// object
// global
Looks like altering the scope of the outer function has no effect on the scope of the inner self-invocation function.
PS: The question is not about how to alter the scope of the inner function. But what is the proper explanation in the "Javascript language" perspective? Does all self executing functions have 'global' scope by default? If so, why?
Your problem is the this and what it references:
foo: function(){
console.log(this.prop);
(function bar(){
console.log(this.prop); <--- this does not reference to foo here, but instead it refers to the window object
})();
}
You need to keep a reference to the outer this:
foo: function(){
console.log(this.prop);
var that = this;
(function bar(){
console.log(that.prop); <--- tada!
})();
}
Update
Some explanation. It's all about how JavaScript determines the context when invoking a function.
function Test() {
this.name = "Test";
this.bar = function() { console.log("My name is: "+ this.name);}
}
function Blub() {
this.name = "Blub";
this.foo = function() { console.log("My name is: " + this.name);}
}
var a = new Test();
var b = new Blub();
// this works as expected
a.bar(); // My name is: Test
b.foo(); // My name is: Blub
// let's do something fun
a.foo = b.foo; // make an educated guess what that does...
a.foo() // My name is: Test
Huh? Aren't we referencing the method of Blub? No we're not. We are referencing the unbound function of Blub.
JavaScript binds on . (dots) and based on that it decides waht the value of this should be.
Since you're not calling your anonymous function on an object (therefore no .) it will make this reference to the global object, which is - in case of the browser - the window object.
Another example (one might think this would work):
var str = "Hello World";
var ord = str.charCodeAt; // let's make a little shortcut here.... bad idea
ord(0) // no dot...
Instead of the char codes that are in str we get the ones that are in the global object, of course that's not a string so charCodeAt calls toString on which results in "[object DOMWindow]"
You are not applying any object as the this context when you call the inner function, so it gets this set to window by default. If you wanted to call the closure with the same this as the outer function, you would have to do:
(function bar(){
console.log(this.prop);
}).call(this);
Or:
var that = this;
(function bar(){
console.log(that.prop);
})();