Why is "this" pointing to the "window Object" in the callback function? - javascript

var callBackFunc = {
value : "CallBackValue",
getValue : function(callback) {
callback();
}
}
var TestingFunc = {
value : "TestingValue",
alertValue : function() {
console.log(this);
}
}
$(function() {
callBackFunc.getValue(TestingFunc.alertValue);
});
I don't want answers to be able to use it properly, but I wonder why "this" points to Window Objects. Plz... Help me!!

because arguments passed by value which means
callBackFunc.getValue(TestingFunc.alertValue);
equals to
callBackFunc.getValue(function() {
console.log(this);
});
so ,callback() works
(function() {
console.log(this);
})()
so ,you get window.
If arguments passed by name ,in this case name is TestingFunc.alertValue,then you will get what you want like :
callback() equals to TestingFunc.alertValue()
However,js works by value not name

The plain callback function reference is passed as a parameter to the callBackFunc.getValue, so there is no current this context will be formed with the plain function and the default this leads to the global object (window).
In order to form the context, we can use call, bind, apply methods.

Related

Java script call by reference

I have to call setTimeout() with parameter grpname,but initially it has not been declared but i want it to refer to the same value if change afterwords...
function test(grpname) {
$('.middle').load("display.php", {
"grpname": grpname
});
}
$(document).ready(function (e) {
$('#inv').hide("fast");
$('#t2').hide("fast");
$('#username').click(function () {
document.userid.username.value = "";
});
var grpname = document.userid.grpname.value;
$('#signup').click(function () {
$('#username').focus();
});
$('#signin').click(function () {
var username = document.userid.username.value;
setTimeout(test.bind(null, grpname), 1000);
....
}
In JavaScript, primitive parameters are passed by value and object parameters are passed by reference. (https://snook.ca/archives/javascript/javascript_pass)
Observe this fiddle: https://jsfiddle.net/8hkmysr1/8/
When the callback function runs, param1 is unaffected by the change to the global value, as it was passed by value. param2 is affected as it was passed by reference.
So you must either pass an object to the function so that the closure references the original object, or you must declare the variable in the global scope and read that value.

Javascript nested function losing scope

Can someone explains the scope binding of the following code please
window.name = "window";
object = {
name: "object",
method: function() {
nestedMethod: function() {
console.log(this.name);
}
nestedMethod();
}
}
object.method(); // print 'window'
I think my question is more about this...why is this losing the scope and default to the global scope ? do all the anonymous functions that we created will go on the global scope ?
Whenever you call a function, simply by writing func(), this inside the function will point to the global object. In your case you write:
nestedMethod();
So this inside nestedMethod is the window object. You can use call (or apply) to manually define a context for you function call:
nestedMethod.call(this);
Any function that's invoked like this:
someFunction();
will have the global scope as the value of this (in non-strict mode). You can either stash the outer scope in a local variable, or else use .call() or .apply():
nestedMethod.call(this);
window.name = "window";
object = {
name: "object",
method: function () {
var self = this;
var nestedMethod = function () {
console.log(self.name); // or object.name without declaring self
}
nestedMethod();
}
}
object.method(); // print 'object'
Save the scope of the object - or use the object itself!
do all the anonymous functions that we created will go on the global scope ?
No, not all the anonymous functions lose their scope, all the functions scopes are bound to the global object(if they are not called with specific this, see apply and call, see the example below)!
window.name = "window";
object = {
name: "object",
method: function () {
var nestedMethod = function () {
console.log(this.name);
}
nestedMethod.call(this); //change the this arg in the current object scope
// when you call this function with .call(this) you are changing the value of the nestedMethod's this to the current this, which is object
}
}
object.method(); // print 'object'
you should declare nested function like this:
Super.prototype.someFunc = function() {
this.nestedFunc = function() {}
//now call it
this.nestedFunc()
}

I don't understand why the "this" keyword doesn't work as I expect

What I want to do is to execute the create_tag function when a specified condition is satisfied. I am referring to this function as a method of an object, in this case document.body, by setting as its method an external function, "create_tag(..)". The problem is inside this function I have a "this" keyword which I would expect to refer to the method's parent, document.body. Instead it doesn't seem to work. I tried replacing "this" with "document.body" in the function so the problem should be caused by "this".
Here is the code:
xmlDom=xmlhttp.responseXML;
hint_ul=document.getElementById("hint_ul");
personaggi=xmlDom.documentElement.getElementsByTagName("personaggio");
for(i=0;i<personaggi.length;i++){
personaggio=personaggi.item(i);
name=personaggio.childNodes[1].firstChild.nodeValue;
if(name.substr(0, str.length).toLowerCase()==str.toLowerCase()){
document.body.crea_li=create_tag(name);
}
}
}
function create_tag(inner){
a=document.createElement("a");
a.innerHTML=inner;
this.appendChild(a); }
this will be window when called like that.
To get its this as the body element, call it like so...
document.body.crea_li = create_tag.call(document.body, name);
Nowhere in your code is create_tag assigned as a method of document.body. The closest you get is with the line document.body.crea_li=create_tag(name);, but what's actually happening here is that you are executing create_tag as a member of the global object, and the result of that operation is assigned to document.body.crea_li.
You could make a reference to this outside the function body - referencing it within the scope later:
var self = this;
function create_tag(inner){
a=document.createElement("a");
a.innerHTML=inner;
self.appendChild(a);
}
This could be a nice trick. When I make complicated javascript objects involving many objects and functions, at the top of the object I create:
var self = this;
as that will live within the scope, the root object is always accessible.
Here is a working example of how I would implement this:
SomeReallyComplexThing = function() {
var self = this;
var foo = 'bar'
this.fooThing = 'Other thing'
this.setSomeData = function(){
console.log('Some data set', arguments)
}
this.makeMassiveCall = function() {
var completeFunc = function(){};
var url = '/some/endpoint.json';
var requestData = {};
jQuery.get(url, requestData, function(data) {
/*
* Data has come back
*/
self.setSomeData(data)
completeFunc(data);
});
}
}
//outside the scope
s = new SomeReallyComplexThing()
s.fooThing() //visible
s.self //undefined
this in javascript is a sqirrely fellow. The idea is this refers to the current function context.
This means that when your running code inside the function this refers to that function's context, which does not have an appendChild method.
Normally you use a closure to keep a reference to the calling context around, something like this
var _self = this;
var result = func();
function func()
{
// _self is the calling context, this is the current context
}
Or you could pass a reference to the calling context:
document.body.crea_li=create_tag(name,this);
function create_tag(inner, context) { context.body.appendChild(...) }
this is referring to the function's parent, but its parent is actually the window object, not the document object or document.body. this actually refers to wherever context the function is called from, and in my opinion you should avoid using it to call methods just for that reason because it can be difficult to see what this is actually referring to. For example, if you called a function using this from another function, it would refer to the context within that function.
This example might help show what's going on:
var hello = function() {
alert( this.message );
}
window.message = "hello!";
hello()
You could document.body directly in the code like you suggested before, or you could pass another parameter that tells the function where to append the created tag:
function create_tag(inner, elementToAddTag){
a=document.createElement("a");
a.innerHTML=inner;
elementToAddTagTo.appendChild(a);
}

getting the "this" that a function's caller was called with in JavaScript

Is it possible to get the this that a function's caller was called with in JavaScript without passing this to the arguments in a way which supports IE as well as Firefox/Chrome et al?
For example:
var ob = {
callme: function() {
doSomething();
}
}
ob.callme();
function doSomething() {
alert(doSomething.caller.this === ob); // how can I find the `this` that
// `callme` was called with
// (`ob` in this case) without
// passing `this` to `doSomething`?
}
I'm starting to suspect it's not, but I thought I may as well ask as it'd make my code much shorter and easier to read.
Well, the closest I can think, without technically passing the value as an argument, would be to set the this value of the doSomething function.
Since the doSomething function is not bound to any object, by default, if you call it like doSomething(); the this value inside it will refer to the Global object, and that's normally not too useful...
For example:
var ob = {
callme: function () {
doSomething.call(this); // bind the `this` value of `doSomething`
}
};
function doSomething () {
alert(this === ob); // use the bound `this` value
}
ob.callme();

How does jQuery hijack "this"?

I'm just curious to know how jQuery is able to hijack the 'this' keyword in Javascript. From the book I'm reading: "Javascript the Definitive Guide" it states that "this" is a keyword and you cannot alter it like you can with an identifier.
Now, say you are in your own object constructor and you make a call to some jQuery code, how is it able to hijack this from you?
function MyObject(){
// At this point "this" is referring to this object
$("div").each(function(){
// Now this refers to the currently matched div
});
}
My only guess would be that since you are providing a callback to the jQuery each() function, you are now working with a closure that has the jQuery scope chain, and not your own object's scope chain. Is this on the right track?
thanks
You can change the context of a function (i.e. the this value) by calling it with .call() or .apply() and passing your intended context as the first argument.
E.g.
function fn() {
return this.foo;
}
fn.call({foo:123}); // => 123
Note: passing null to either call or apply makes the context the global object, or, in most cases, window.
It's probably worth noting the difference between .apply() and .call(). The former allows you to pass a bunch of arguments to the function it's being applied to as an array, while the latter lets you just add them as regular arguments after the context argument:
someFunction.apply( thisObject, [1,2,3] );
someFunction.call( thisObject, 1, 2, 3 );
From the jQuery source:
for ( var value = object[0];
i < length &&
callback.call( value, i, value ) // <=== LOOK!
!== false;
value = object[++i] ) {}
It doesn't hijack anything - it just makes sure that "this" is pointing at what it wants it to. Look up the standard "call" function that's available for any Javascript function object.
See the documentation for Function.apply. The first parameter is the "context". It can be any object. If null, it will be scoped globally.
The function type in JavaScript has a method called apply() which allows you to specify to what object this is bound at. Its signature is:
apply(thisObj, arguments);
Once called, it calls the function binding this to thisObj and passing the arguments arguments.
It is usually used as such:
function product(name, value)
{
this.name = name;
if (value > 1000)
this.value = 999;
else
this.value = value;
}
function prod_dept(name, value, dept)
{
this.dept = dept;
product.apply(this, arguments);
}
prod_dept.prototype = new product();
// since 5 is less than 1000 value is set
var cheese = new prod_dept("feta", 5, "food");
// since 5000 is above 1000, value will be 999
var car = new prod_dept("honda", 5000, "auto");
try this:
var MyObject = { "Test": "Hello world!" };
(function ()
{
alert(this.Test); // Gives "Hello world!"
}).call(MyObject);
(function ()
{
alert(this.Test); // Gives "Hello world!"
}).apply(MyObject);
(function ()
{
alert(this.Test); // Gives "undefined"
})()
function.apply() and function.call() allow you to change what this points to in Javascript. Here's a couple of handy articles that explain it in greater detail - Scope In Javascript and Binding Scope in Javascript

Categories