what does 'this' refer to in Javascript functions - javascript

I understand the general idea behind the this keyword but I'm having trouble figuring out what it actually refers to in practice. For example, in both these example exercises, I guessed the wrong number.
for question1, I said that the alert would be '5', because it is referring to the this.x outside the anonymous function in the function.
In question2, I thought the alert would be 5 because this line
var alertX = o.alertX;
would bind the value 5 for property x inside the variable o to the new variable 'alertX' which becomes the function call in the next line: alertX();
Can you explain why I'm wrong?
var question1 = function() {
this.x = 5;
(function() {
var x = 3;
this.x = x;
})();
alert(this.x);
};
var answer1 = 3;
var question2 = function() {
this.x = 9;
var o = {
'x':5,
'alertX':function() { alert(this.x); }
};
var alertX = o.alertX;
alertX();
}
var answer2 = 9;

In the first case, when you invoke a method with no explicit receiver this is the Global object (the window in a web browser).
Similarly in the second case: even though the function is defined on the object, and you are inside another, by invoking the function with alertx() the this is set to the Global/window.
In short:
For foo.bar(), the this inside of bar will be foo.
For bar(), the this will be the Global object.
This includes so-called "self-invoking lambdas", i.e. (function(){ ... })().
For bar.call(whee) and bar.apply(whee), the this will be whee (because that's what these methods do).
Another example:
var o1 = { name:"o1", f:function(){ console.log(this.name) } };
var o2 = { name:"o2" };
o2.gogogo = o1.f;
o2.gogogo(); // Will output "o2"

These are good examples of how interesting this becomes in Javascript. this always refers to the context in which it was invoked / called, not simply where it is at that moment! question2 is a perfect example of it.
I'm assuming you are invoking these globally like so:
question1();
question2();
In question1:
You have an anonymous function that is ran after you first set x to 5. This anonymous function if not set to a variable, inside a function etc, would have this set to the global variable of window. But you have it within a function & set to variable question1. So when it runs itself, it sets this's (which is question1 function) x variable to 3.
In question2:
X is originally set to 9, this being question2 in this instance. Now the part that is throwing you off is that, even though within the o {} object you set x : 5. And your alertX function is calling this.x. All of this would lead you to think it will alert 5! But you are invoking your alert function outside of the o {} object, hence the this refers to question2 function again!

Put the following into your browser's console
var x = -1, log = function(){ // set up some stuff
if(console) if(console.log) return console.log.apply(console, arguments),undefined;
return alert(arguments.join(', ')),undefined;
},
question1 = function() {
this.x = 5; // question1.x is 5
(function() { // anonymous function fires in global 'window'
var x = 3; // so window.x is now 3
this.x = x; // this is window
})();
log('ans1',this.x,this); // see below
},
question2 = function() {
this.x = 9; // question2.x is 9
var o = {
'x':5, // o.x is 5
'alertX':function() { log('ans2',this.x,this); }
};
var alertX = o.alertX; // alertX === o.alertX
alertX(); // being called in global scope
// to make alertX have scope of question2
this.alertX = o.alertX; // this is question2
this.alertX(); // so we're calling from question2
},
a1 = new question1(), // note the new operator
a2 = new question2();
undefined;
And you'll get
ans1 5 question1
ans2 3 Window
ans2 9 question2

Related

Interview test about the clousure in the javascript? [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 5 years ago.
This is an interview question! And I can't know the reason of it!
function fun(val) {
this.x = val;
return this;
}
var x = fun(1);
var y = fun(2);
console.log(x.x); //I can't understand this result.
console.log(y.x);
Well, I think that happens because "This" in the fun function refers to Window object not a local thing inside the function. so therefore you first call it by fun(1) and make the window.x = 1, and then call it by fun(2) and it becomes window.x = 2 .. then you console log it when both x and y are a reference to window ... and therefore both will have the same final value.
When you call a function the "normal" way, the this object points to the global object (window):
function testFunction () {
return this;
}
console.log(window === testFunction());
This means that what your function returns is the global object, and both variables x and y are references to the global object. Before it returns, it assigns a property x to the global object.
In the first function call, it assigns 1 to the property x of the global object. In the second function call, it assigns 2 to the same property. This is why you get 2 two times.
If you want this to refer to another object than the global one, you have to use call:
function testFunction (value) {
this.x = value;
return this;
}
var firstObject = {};
var secondObject = {};
var x = testFunction.call(firstObject, 1);
var y = testFunction.call(secondObject, 2);
console.log(x.x);
console.log(y.x);
console.log(x === firstObject);
console.log(y === secondObject);
console.log(window === testFunction());

Does assigning a function to a variable in javascript run the function

I have three simple programs below with different outputs. I am a bit confused as to why I get a different output. What really happens when you assign a function to a variable? Does it not run unless you have parentheses (i.e. myfunction())? I'm also very confused as to how JavaScript allows the parenthesis behind a function as 'optional' when calling it. Can someone clear this up? I only know Java so this is all new territory for me.
// ------First--------------------------------
var x = 9;
function myfunction (){
x = 3;
}
var w = myfunction;
w();
console.log(x);
//output is 3
// ---------Second -----------------------------
var x = 9;
function myfunction (){
x = 3;
}
var w = myfunction;
console.log(x);
//output is 9
// ---------Third -----------------------------
var x = 9;
function myfunction (){
x = 3;
}
var w = myfunction();
console.log(x);
//output is 3
No, it does not. A reference to a function by name is simply a reference to a value, like any other value. Without the () operator, it's not a function call.
Parentheses are not optional when calling a function except when it's being called via the new operator. Thus:
function foo() {
console.log("hi!");
}
var otherFoo = foo; // no function call
var obj = new foo; // function call via "new"
var x = foo(); // function call via "()"

JavaSCript Example (Oreilly book)

Methods(Object's function) can refer to object's variable using the "this" keyword.
Can function's properties refer to function variables?
Eg:-
function foo()
{
var x=5;
}
foo.help = {o1:x};// o1 is not initialized to x.
//Using o1:this.x also doesn't help. Why? Explain please.
Is there anyway to initialize o1 to x?
Example 9-1. A simple JavaScript class
// range.js: A class representing a range of values.
// This is a factory function that returns a new range object.
function range(from, to) {
// Use the inherit() function to create an object that inherits from the
// prototype object defined below. The prototype object is stored as
// a property of this function, and defines the shared methods (behavior)
// for all range objects.
var r = inherit(range.methods);
// Store the start and end points (state) of this new range object.
// These are noninherited properties that are unique to this object.
r.from = from;
r.to = to;
// Finally return the new object
return r;
}
// This prototype object defines methods inherited by all range objects.
range.methods = {
// Return true if x is in the range, false otherwise
// This method works for textual and Date ranges as well as numeric.
includes: function(x) { return this.from <= x && x <= this.to; },
// Invoke f once for each integer in the range.
// This method works only for numeric ranges.
foreach: function(f) {
for(var x = Math.ceil(this.from); x <= this.to; x++) f(x);
},
// Return a string representation of the range
toString: function() { return "(" + this.from + "..." + this.to + ")"; }
};
// Here are example uses of a range object.
var r = range(1,3); // Create a range object
r.includes(2); // => true: 2 is in the range
r.foreach(console.log); // Prints 1 2 3
console.log(r); // Prints (1...3)
What I understand :
Range is a function with variable from and to.
Range.methods is Range's property.It is defined outside Range() but it can still access from and to (using this.from and this.to ). How?
Thank you.
EDIT
this answer is based on edited question -- original answer is below
Your understanding is a little backwards.
The function doesn't have from and to in the way you think it does.
If I built this a different way, to get almost all of the same functionality, but be much, much easier for a person who is new to JS to understand, I would write it like this:
// my `makeRange` function makes an object
// then it gives it all of the things a range object needs
// then it returns the new object
var makeRange = function (min, max) {
// there are cleaner more-compact ways of doing this
// I'm writing this out in long-form to show you exactly what's going on
var rangeObject = {};
rangeObject.from = min;
rangeObject.to = max;
rangeObject.includes = includes;
rangeObject.foreach = foreach;
rangeObject.toString = toString;
return rangeObject;
};
// these are all of the functions inside of `range.methods`
// they don't have to be attached to the function ***AT ALL***, for ***ANY REASON***
// other than the author wanted them to be there for the sake of organization
// Here, I'm just putting them out on their own, for sake of clarity
var includes = function (x) { return this.from <= x && x <= this.to; },
foreach = function (func) {
var min = this.from,
max = this.to,
i = 0;
for (i = min; i <= max; i += 1) { func(i); }
},
toString = function () { return "(" + this.from + "..." + this.to + ")"; };
var range_3_to_5 = makeRange(3, 5),
range_6_to_12 = makeRange(6, 12);
range_3_to_5.from; // 3
range_6_to_12.includes(8); // true
range_6_to_12.foreach(function (i) { console.log(i); }); // [logs:] 6,7,8,9,10,11,12
The methods on range in the example aren't a part of the function.
They're methods which are given to the objects, as they are constructed.
In the example you gave, this is happening inside of the r = inherit(range.methods); call, which isn't explained in that block of code.
The this doesn't refer to the function at all.
It refers to the final object which uses the methods, at the time the method is called.
My range_3_to_5 and range_6_to_12 are both using the same copy of includes.
When range_3_to_5.includes(6); is called, this is set to range_3_to_5, and then the function uses this.from and this.to to determine if x is in the range.
There's no complex magic here.
We're just calling a function which "makes" something in a specific way, like a factory assembly-line, and then passes the finished version out.
It's attaching shared functions to each copy on the assembly line, and those shared functions use this to figure out which copy they're dealing with at the time.
var car = { license : "a32 vx98" },
truck = { license : "vdx 2000" },
jeep = { license : "mkv 3a2b" };
var read_license = function () { console.log(this.license); };
car.read_license = read_license;
truck.read_license = read_license;
car.read_license(); // [logs:] a32 vx98
truck.read_license(); // [logs:] vdx 2000
I can even call the function on its own, using the function's .call or .apply method to manually set this.
read_license.call(jeep); // [logs:] mkv 3a2b
Or use .bind to save a version of the function which ALWAYS uses the same value for this.
var read_car_license = read_license.bind(car);
read_car_license(); // a32 vx98
previous answer below
Not even remotely.
Variables live inside of the functions that they're created in:
var myFunction = function () {
var myValue = 23;
console.log(myValue);
};
myFunction(); // [log:] 23
console.log(myValue); // undefined
Values can live inside of functions further in:
var myFunction = function () {
var myValue = 23,
sayValue = function () {
console.log(myValue);
};
sayValue(); // will log 23 when you call `myFunction`
}
myFunction(); // [log:] 23
But if you want your variable to live OUTSIDE of the function (instead of further inside), then you either need to return the value to something, or set it to something, directly, from inside of the function.
var myOutsideValue = 42,
myFunction = function () {
var myValue = 23;
myOutsideValue = myValue;
};
console.log(myOutsideValue); // 42
myFunction();
console.log(myOutsideValue); // 23
Or returned...
var myReturnedValue = 0,
myFunction = function () {
var myValue = 23;
return myValue;
};
myReturnedValue = myFunction();
console.log(myReturnedValue); // [log:] 23
Or you can pass in an array or object to modify:
var myObject = {},
myFunction = function (obj) {
var myValue = 23;
obj.value = myValue;
};
myFunction(myObject);
console.log(myObject.value); // [log:] 23
Functions CAN reference themselves.
And because in JavaScript, functions are objects (and can have their own properties and methods), you can add things to them the same way you'd add properties to any {} object.
var myFunc = function () {
var myValue = 23;
myFunc.properties = {};
myFunc.properties.value = myValue;
};
myFunc();
console.log(myFunc.properties.value); // [logs:] 23
None of this has anything to do with this.
this is used for the opposite of what you're looking for.
It's for when you're inside a function which is attached to an object, and you want to read other properties/run other methods that are on that object.
var myObject = {
x : 23,
y : 42,
sayX : function () { console.log(this.x); },
sayY : function () { console.log(this.y); }
};
myObject.sayX(); // [logs:] 23
this is used in a couple of other spots, but really, that's it's primary role: accessing or setting values/methods on the object which the function is attached to (either through dot-property access obj.func(), or through manual setting, using .call/.apply/.bind), with the other very regular situation being the creation of new objects, using the new keyword.
So the way to get your x to work isn't to figure out this, it's to set it within the function, itself, or, more-appropriately, pass x out (return x) to another variable, outside, and then set the value yourself.
var foo = function () {
var x = "x";
return x;
},
variable; // === undefined
foo.help = { o1 : 0 };
variable = foo(); // variable === "x"
foo.help.o1 = variable;
// or shorter: foo.help.o1 = foo();
Alternative:
var help = { o1 : 0 },
foo = function (obj) {
var x = "x";
obj.o1 = x;
};
foo(help);
foo.help = help;
this only works inside of functions
var obj = {};
obj.x = 12;
obj.y = this.x + 5; // DOESN'T WORK
If this works in the last example, it's only because it's using this from inside of a function which would be referring to the FUNCTION'S this, and not to obj. And if you're calling a function which isn't attached to an object (obj.func(); or func.call(obj) or new_func = func.bind(obj);), then this will point to window.
In the context foo.help = {o1: x}, you are not in the same lexical scope as the definition of x, which would be inside of the foo function scope. This also applies to this.x (which apply in object scope).
function foo() {
var x = 5;
this.help = x;
}

Declaring variables with this or var?

What is the difference between declaring a variable with this or var ?
var foo = 'bar'
or
this.foo = 'bar'
When do you use this and when var?
edit: is there a simple question i can ask my self when deciding if i want to use var or this
If it is global code (the code is not part of any function), then you are creating a property on the global object with the two snippets, since this in global code points to the global object.
The difference in this case is that when the var statement is used, that property cannot be deleted, for example:
var foo = 'bar';
delete foo; // false
typeof foo; // "string"
this.bar = 'baz';
delete bar; // true
typeof bar; "undefined"
(Note: The above snippet will behave differently in the Firebug console, since it runs code with eval, and the code executed in the Eval Code execution context permits the deletion of identifiers created with var, try it here)
If the code is part of a function you should know that the this keyword has nothing to do with the function scope, is a reserved word that is set implicitly, depending how a function is called, for example:
1 - When a function is called as a method (the function is invoked as member of an object):
obj.method(); // 'this' inside method will refer to obj
2 - A normal function call:
myFunction(); // 'this' inside the function will refer to the Global object
// or
(function () {})();
3 - When the new operator is used:
var obj = new Constructor(); // 'this' will refer to a newly created object.
And you can even set the this value explicitly, using the call and apply methods, for example:
function test () {
alert(this);
}
test.call("hello!"); //alerts hello!
You should know also that JavaScript has function scope only, and variables declared with the var statement will be reachable only within the same function or any inner functions defined below.
Edit: Looking the code you posted to the #David's answer, let me comment:
var test1 = 'test'; // two globals, with the difference I talk
this.test2 = 'test'; // about in the beginning of this answer
//...
function test4(){
var test5 = 'test in function with var'; // <-- test5 is locally scoped!!!
this.test6 = 'test in function with this'; // global property, see below
}
test4(); // <--- test4 will be called with `this` pointing to the global object
// see #2 above, a call to an identifier that is not an property of an
// object causes it
alert(typeof test5); // "undefined" since it's a local variable of `test4`
alert(test6); // "test in function with this"
You can't access the test5 variable outside the function because is locally scoped, and it exists only withing the scope of that function.
Edit: In response to your comment
For declaring variables I encourage you to always use var, it's what is made for.
The concept of the this value, will get useful when you start working with constructor functions, objects and methods.
If you use var, the variable is scoped to the current function.
If you use this, then you are assigning a value to a property on whatever this is (which is either the object the method is being called on or (if the new keyword has been used) the object being created.
You use var when you want to define a simple local variable as you would in a typical function:-
function doAdd(a, b)
{
var c = a + b;
return c;
}
var result = doAdd(a, b);
alert(result);
However this has special meaning when call is used on a function.
function doAdd(a, b)
{
this.c = a + b;
}
var o = new Object();
doAdd.call(o, a, b);
alert(o.c);
You note the first parameter when using call on doAdd is the object created before. Inside that execution of doAdd this will refer to that object. Hence it creates a c property on the object.
Typically though a function is assigned to a property of an object like this:-
function doAdd(a, b)
{
this.c = a + b;
}
var o = new Object();
o.doAdd = doAdd;
Now the function can be execute using the . notation:-
o.doAdd(a, b);
alert(o.c);
Effectively o.doAdd(a, b) is o.doAdd.call(o, a, b)
var foo = 'bar'
This will scope the foo variable to the function wrapping it, or the global scope.
this.foo = 'bar'
This will scope the foo variable to the this object, it exactly like doing this:
window.foo = 'bar';
or
someObj.foo = 'bar';
The second part of your question seems to be what is the this object, and that is something that is determined by what context the function is running in. You can change what this is by using the apply method that all functions have. You can also make the default of the this variable an object other than the global object, by:
someObj.foo = function(){
// 'this' is 'someObj'
};
or
function someObj(x){
this.x=x;
}
someObj.prototype.getX = function(){
return this.x;
}
var myX = (new someObj(1)).getX(); // myX == 1
In a constructor, you can use var to simulate private members and this to simulate public members:
function Obj() {
this.pub = 'public';
var priv = 'private';
}
var o = new Obj();
o.pub; // 'public'
o.priv; // error
Example for this and var explained below:
function Car() {
this.speed = 0;
var speedUp = function() {
var speed = 10; // default
this.speed = this.speed + speed; // see how this and var are used
};
speedUp();
}
var foo = 'bar'; // 'var can be only used inside a function
and
this.foo = 'bar' // 'this' can be used globally inside an object

Pass in jQuery/plainJS variables/functions of a current scope to anonymous function called from current scope

How to pass current scope variables and functions to the anonymous function in plain Javascript or in jQuery (if it's specific for frameworks).
For example:
jQuery.extend({
someFunction: function(onSomeEvent) {
var variable = 'some text'
onSomeEvent.apply(this); // how to pass current scope variables/functions to this function?
return null;
_someMethod(arg) {
console.log(arg);
}
}
});
Should log in firebug everything from the function above:
jQuery.someFunction(function(){
console.log(this.variable); // or console.log(variable);
console.log(this._someMethod(1); // or jQuery.someFunction._someMethod(2);
});
Thanks!
Read about Scopes in JavaScript for example in "Java Script: The good parts".
In the Java Script there is only scope inside Functions.
If you specify your variable inside function with var you can't access them from outside of this function. This is way to make private variables in JavaScript.
You can use this variable, that point to current object you are in (this is not a scope itself). But! if you initiate function without new command, than this will point to outer scope (in most cases it's window object = global scope).
Example:
function foo(){
var a = 10;
}
var f = foo(); //there is nothing in f
var f = new foo(); //there is nothing in f
function bar(){
this.a = 10;
}
var b = new bar(); //b.a == 10
var b = bar(); //b.a == undefined, but a in global scope
Btw, check out syntax of apply method Mozilla docs/apply
So you can see, that fist argument is object, that will be this when your method will be called.
So consider this example:
function bar(){
console.log(this.a);
console.log(this.innerMethod(10));
}
function foo(){
this.a = 10;
this.innerMethod = function(a){
return a+10;
}
bar.apply(this);
}
var f = new foo(); // => you will get 10 and 20 in the console.
var f = foo(); // => you will still get 10 and 20 in the console. But in this case, your "this" variable //will be just a global object (window)
Maybe it's better to make
var that = this;
before calling apply method, but maybe it's not needed. not sure
So, this definitely will work:
function foo(){
console.log(this.a);
}
jQuery.extend({
somefunc: function(func){
this.a = 10;
func.apply(this);
}
});
$.somefunc(foo); //will print 10.
Before line 1:
var that = this;
Then change line 4:
onSomeEvent.apply(that);

Categories

Resources