This question already has answers here:
What is the difference between a function call and function reference?
(6 answers)
Closed last year.
I was following a tutorial on AJAX, and the person making the video did something strange. At least I hadn't seen it before. They set an object property equal to a function name, but without the familiar (). He later went on to define the function. Code is provided below for context. Anyway, what does it mean to set something equal to a function without the parameters? That line of code is indeed running the function that is named that as you can see below.
xmlHTTP.onreadystatechange = handleServerResponse;
There's a function called "handleServerResponse()", that this line actually runs. I can post it, but I think it's irrelevant. It's just a normal function function handleServerResponse(). Any explanation would be greatly appreciated!
Thanks!
~Carpetfizz
EDIT: Adding () to the end of that line, creates errors, as well as changing it.
What they're doing there is referring to the function without calling it.
var x = foo; // Assign the function foo to x
var y = foo(); // Call foo and assign its *return value* to y
In JavaScript, functions are objects. Proper objects. And so you can pass references to them around.
In that specific case, what they're doing is setting up handleServerResponse as the callback that the XHR object uses when the ready state changes. The XHR object will call that function during the course of doing the ajax request.
Some more examples:
// Declare a function
function foo() {
console.log("Hi there");
}
// Call it
foo(); // Shows "Hi there" in the console
// Assign that function to a varible
var x = foo;
// Call it again
x(); // Shows "Hi there" in the console
// Declare another function
function bar(arg) {
arg();
}
// Pass `foo` into `bar` as an argument
bar(foo); // Shows "Hi there" in the console, because `bar`
// calls `arg`, which is `foo`
It follows on naturally from the fact that functions are objects, but it's worth calling out specifically that there's no magic link between x and foo in the above; they're both just variables that point to the same function. Other than the fact they point to the same function, they're not linked in any way, and changing one (to point at another function, for instance) has no effect on the other. Example:
var f = function() {
console.log("a");
};
f(); // "a"
var x = f;
x(); // "a"
f = function() {
console.log("b");
};
f(); // "b"
x(); // "a" (changing `f` had no effect on `x`)
When the state of the request changes (for example when the browser received the complete answer), the browser will call a function stored in the onreadystatechange property of the xmlHttpRequest. This call will be something like
xmlHTTP.onreadystatechange();
which will be just equivalent to
handleServerResponse();
To decide what function will be called, you assign this function (not the returned value of this function) to this property using the line you show.
This is possible because JavaScript is a language where functions are said first class : they may be property values just like objects, strings, etc.
It means you are assigning the variable a reference to that function. The reference then can be used to call the function instead. Something like this...
function foo(){
alert("I am inside foo");
}
var bar = foo; // bar now points to foo
// Call foo
foo();// alerts "I am inside foo";
// Call bar which is pointing to foo
bar();// alerts "I am inside foo";
Related
I have following code, I am expecting alert('baz') but it is not working
var foo = function () {
function foo() {
alert('foo');
}
foo.baz = function () {
alert('baz');
}
}
foo().baz();
However If I return foo at the end it works
var foo = function () {
function foo() {
alert('foo');
}
foo.baz = function () {
alert('baz');
}
return foo;
}
foo().baz(); // output:baz
why first one not working and why second is working and what is purpose inner foo??
Because chaining method needs to be returned something. So, in your code you are correctly returning the foo and then it's getting called.
The first one is not working, because the "foo" method is not a void, so it expects a return value. Without a return value, the call to the method will fail. I advice you to trace both of the calls in developer tools, breakpoint each and trace step by step the chain of events.
As for your second question, The purpose is simple, to give foo additional functionality. Usually you won't use nested foo, it's a bad practice, but a prototype. As with an account method. It contains first name, last name and account number, then a prototype of the method is created in order to create withdraw and deposit methods for the specific account.
It's almost identical to working with polymorphic objects in C# or JAVA. instead using override, you use prototype, or in the case of the code above, nested "foo".
In your code you are assigning the function to a variable and not normally. The variable name can be used by the code inside the function to refer the function itself, but the code outside the function can not see it at all.
When you call the function like foo().baz();
it will first call the foo() function and will need a return value (in this case a function referer variable). Then according to the referer variable name it will call the baz() inside the foo(). So to call the function baz() inside foo(), you need to access function first.
Unfortunately .bind has been giving me grief when creating more complex closures.
I am quite interested in why .bind seems to work differently once you nest functions.
For example :
function t(){
t = t.bind({}); //correctly assigns *this* to t
function nested_t(){
nested_t = nested_t.bind({}); // fails to assign *this* to nested_t
return nested_t;
}
return nested_t();
}
//CASE ONE
alert(t());
// alerts the whole function t instead of nested_t
//CASE TWO
aleft(t.call(t));
// alerts the global object (window)
In both cases I was expecting a behavior like this:
function t(){
var nested_t = function nested_t(){
return this;
};
return nested_t.call(nested_t);
}
alert(t.call(t));
If someone could explain the behavior of .bind in the first (and/or) second case it would be much appreciated!
So, i'm not entirely reproducing your issue here (both cases return the global object), but i'll try and explain the code as i see it.
function t(){
t = t.bind({}); //correctly assigns *this* to t
function nested_t(){
nested_t = nested_t.bind({}); // fails to assign *this* to nested_t
return this;
}
return nested_t();
}
//CASE ONE
alert(t());
Let's take it step by step.
First, the function t() is defined. Then, upon call, it gets overwritten with a clean context. However, i don't see any usage of this context.
Now, a nested function (nested_t) is defined. Upon call, it is overwritten with a clean context. It then returns the context it had when it was called.
Back to t(). You then return the result of nested_t(), not nested_t itself. In the original function call, nested_t is still being called with global context.
Therefore, when you run t(), it returns the global object.
How your code works
It's very unclear, what your code is trying to do. You can find the documentation for .bind() here. It looks like you might be somehow misunderstanding what this is and how to use it. Anyway, what happens when you run your code is this:
A t function is created in global scope.
[case one] The t function is called.
Global scope t is replaced with a new value (original t bound to a specific context - anonymous empty object), which doesn't affect the current call in any way. Also, while the global t is overwritten, the local t is behaving as read-only. You can check it out by trying the following code: (function foo () { return (function bar () { bar = window.bar = 'baz'; return bar; })(); })() and comparing return value with window.bar.
The same thing happens with nested_t in the nested context (instead of global context).
Result of nested_t call is returned. nested_t returns the context it was called with, which was window, as no context was specified. Specifically, it was not called with an empty object context, because the .bind() inside didn't affect the call itself.
[case two] The exact same thing happens once again. Now you're just calling t with itself as context. Since t doesn't use its context (this) anywhere in its code, nothing really changes.
What your misconceptions might be
Basically, you're mixing up two things - function instance and function call context. A function is a "first-class citizen" in JavaScript - it's an object and you can assign values to its properties.
function foo () {
foo.property = 'value';
}
foo(); // foo.property is assigned a value
This has nothing to do with function call context. When you call a function a context is assigned to that call, which can be accessed using this (inside function body)
function foo () {
this.property = 'value';
}
var object = {};
foo.call(object); // object.property is assigned a value
When you use .bind(), you just create a new function with the same code, that is locked to a specific context.
function foo () {
this.property = 'value';
}
var fixedContext = {},
object = {};
bar = foo.bind(fixedContext);
foo.call(object); // fixedContext.property is set instead of object.property
But in this case, there are also function instances foo and bar, which can also be assigned properties, and which have nothing to do with contexts of calls of those functions.
Let's look at how bind works. First, one level of nesting:
var foo = function() { return this.x; };
alert(foo()); // undefined
alert(foo.bind({x: 42})()); // 42
Now we can add the next level of nesting:
var bar = function() { return foo.bind(this)(); };
alert(bar()); // undefined
alert(bar.bind({x: 42})());
We pass our this context to foo with - guess what? - bind. There is nothing different about the way bind works between scopes. The only difference is that we've already bound this within bar, and so the body of bar is free to re-bind this within foo.
As a couple of commenters have noted, functions that overwrite themselves are a huge code smell. There is no reason to do this; you can bind context to your functions when you call them.
I highly, highly recommend reading the documentation on bind, and trying to understand it to the point where you can write a basic version of Function.prototype.bind from scratch.
(Question 1)
In Flanagan's JS Definitive Guide, he defines the Function method bind() in case it's not available (wasn't available n ECMAScript 3).
It looks like this:
function bind(f, o) {
if (f.bind) return f.bind(o); // Use the bind method, if there is one
else return function() { // Otherwise, bind it like this
return f.apply(o, arguments);
};
}
He illustrates the use of it with an example (which I have modified to change the 3rd line from f.bind(o)):
function f(y) { return this.x + y; } // This function needs to be bound
var o = { x : 1 }; // An object we'll bind to
var g = bind(f, o); // Calling g(x) invokes o.f(x)
g(2) // => 3
When I first saw this, I thought "Wouldn't arguments refer to the arguments variable within the bind function we're defining? But we want the arguments property of the function we eventually apply it to, like g in the example above..."
I verified that his example did indeed work and surmised that the line return f.apply(o, arguments) isn't evaluated until var g = bind(f, o) up above. That is, I thought, when you return a function, are you just returning the source code for that function, no? Until its evaluated? So I tested this theory by trying out a slightly different version of bind:
function mybind2(f, o) {
var arguments = 6;
return function() { // Otherwise, bind it like this
return f.apply(o, arguments);
};
}
If it's simply returning tbe unevaluated function source, there's no way that it stores arguments = 6 when later evaluated, right? And after checking, I still got g(2) => 3. But then I realized -- if it's just returning unevaluated code, how is the o in return f.apply(o, arguments) getting passed?
So I decided that what must be happening is this:
The o and the arguments variables (even when arguments equals 6) are getting passed on to the function. It's just that when the function g is eventually called, the arguments variable is redefined by the interpreter to be the arguments of g (in g(2)) and hence the original value of arguments that I tried to pass on was replaced. But this implies that it was sort of storing the function as text up until then, because otherwise o and arguments would have simply been data in the program, rather than variables that could be overwritten. Is this explanation correct?
(Question 2) Earlier on the same page, he defines the following function which makes use the apply method to trace a function for debugging:
function trace(o, m) {
var original = o[m]; // Remember original method in the closure.
o[m] = function() { // Now define the new method.
console.log(new Date(), "Entering:", m); // Log message.
var result = original.apply(this, arguments); // Invoke original.
console.log(new Date(), "Exiting:", m); // Log message.
return result; // Return result.
};
}
Wouldn't the this here refer to the function that we're defining, rather than the object o? Or are those two things one and the same?
Question 1
For your first question, let's simplify the example so it's clear what being done:
function bind(func, thisArg) {
return function () {
return func.apply(thisArg, arguments);
};
}
What happens here is that a closure is created that allows the access of the original function and the value of this that is passed. The anonymous function returned will keep the original function in its scope, which ends up being like the following:
var func = function () {};
var thisArg = {};
func.apply(thisArg, [/*arguments*/]);
About your issue with arguments, that variable is implicitly defined in the scope of all functions created, so therefore the inner arguments will shadow the outer arguments, making it work as expected.
Question 2
Your problem is to your misunderstanding of the late binding of this -- this is one of the more confusing things about JavaScript to people used to more object-oriented languages that also have their own this keyword. The value of this is only set when it is called, and where it is called defines the value of this when it is called. It is simply the value of the parent object from where it is at the time the function is called, with the exception of cases where the this value is overridden.
For example, see this:
function a() {return this;};
a(); // global object;
var b = {};
b.a = a;
b.a(); // object b
If this was set when the function was defined, calling b.a would result in the global object, not the b object. Let's also simplify what happens with the second function given:
function trace(obj, property) {
var method = obj[property]; // Remember original method in the closure.
obj[property] = function () { // Now define the new method.
console.log(1); // Log message.
// Invoke original method and return its result
return original.apply(this, arguments);
};
}
What happens in this case is that the original method is stored in a closure. Assigning to the object that the method was originally in does not overwrite the method object. Just like a normal method assignment, the principles of the this value still work the same -- it will return the parent object, not the function that you've defined. If you do a simple assignment:
var obj = {};
obj.foo = function () { return this; };
obj.foo(); // obj
It does what was expected, returns the parent object at the time of calling. Placing your code in a nested function makes no difference in this regard.
Some good resources
If you'd like to learn more about writing code in JavaScript, I'd highly recommend taking a look at Fully Understanding the this Keyword by Cody Lindley -- it goes into much more detail about how the this keyword behaves in different contexts and the things you can do with it.
But this implies that it was sort of storing the function as text up until then, because otherwise o and arguments would have simply been data in the program, rather than variables that could be overwritten. Is this explanation correct?
No. this and arguments are just special variables which are implicitly set when a function is executed. They don't adhere to normal "closure rules". The function definition itself is still evaluated immediately and bind returns a function object.
You can easily verify this with:
var g = bind(f, o);
console.log(typeof g);
Here is a simpler example which doesn't involve higher order functions:
var arguments = 42;
function foo() {
console.log(arguments);
}
foo(1, 2);
I think you see that the definition of foo is evaluated like you'd expect. Yet, console.log(arguments) logs [1, 2] and not 42.
Wouldn't the this here refer to the function that we're defining, rather than the object o? Or are those two things one and the same?
this never refers to the function itself (unless you explicitly set it so). The value of this is completely determined by how the function is called. That's why this is often called "the context". The MDN documentation provides extensive information about this.
Reading material:
MDN - this
MDN - arguments
Follow up question to this one, call javascript object method from html. I'm debugging this in Firebug.
function Fred() {
this.a = 1;
function foo() {
if (a == 1) {
a++;
}
var e = 0;
}
this.bar = function () {
var a = 3;
foo();
};
}
From an HTML file, I create a new instance of Fred and invoke bar(). In Firebug, on the call to bar(), I can see in the Watch view this is my Fred instance. When bar() invokes foo(), this changes to an instance of Window. I would have expected this to remain the same.
Maybe more remedial training on closures.
In JavaScript, if you call a function, the fact where this points to is depending on the context of the call.
Function invocation pattern
If you call a function as a function, i.e.:
foo();
then this will refer to the global context, which in the browser means the window object.
Method invocation pattern
If instead you call a function like a method, i.e.:
x.foo();
then this will refer to the object where you called the function on, i.e. x.
Call / apply invocation pattern
If you want to call a function as a function, and change what this refers to you can use the call or the apply function, such as
foo.call(x);
foo.apply(x);
Both do the same thing: Call foo as if it was called as a method on x. The difference between them is when you want to hand over parameters: call requires you to specify them as a comma-separated list, while apply lets you hand over an array:
foo.call(x, p1, p2, p3, ...);
foo.apply(x, [ p1, p2, p3, ... ]);
Constructor invocation pattern
Just for the sake of completeness, there's even a fourth option of what this may be: If you call a function as a constructor, this points to the newly created object:
new foo();
To make this obvious to everyone, in JavaScript you have the best practice to start the name of a function that acts as a constructor with an upper-case letter, i.e.:
new Foo();
Nevertheless, the effect stays the same.
Use .call() or .apply()
The first paramater states the context in which the following function will be called.
e.g.
this.bar = function () {
var a = 3;
foo.call(this);
};
I've been learning Javascript with Khan Academy. I'm looking at : http://www.khanacademy.org/cs/speed-circles/964929070
there is a line that reads "var draw = function() {...}" is he defining a function called draw? Or is the variable draw calling some function (which I don't see defined)?
Thanks!
Yes, a function expression is being assigned to the variable named draw. You can even call it:
var draw = function() {
console.log('xyz');
};
draw(); // 'xyz'
In JavaScript, functions are objects, just like arrays and -logically- objects are. As you may have found out already these objects can be assigned to a multitude of variables, but as soon as you change one of these variables, they all change. That's because JS always assigns by value, but a variable is never assigned an object directly: it's assigned a reference to an object:
var obj = {iam: 'an object'};
var reassign = obj;
console.log(obj);//shows object
console.log(reassign);//surprize, shows the same thing
reassign.bar = 'foobar';
console.log(obj.bar);//logs foobar, the variable obj has gained the same property, because it is the same object.
The same applies to functions, being objects, the can be assigned to variables/properties all over the place, but it'll still be the same object/function:
var foo = function()
{
console.log('I am an object');
};
var second = foo;
second();//logs I am an object
console.log(second === foo);//logs true, because they both reference the same thing
Why, then, you might ask is an anonymous function being assigned to a variable, instead of just declaring a function as you'd expect? Well:
function foo(){}
is hoisted, prior to running any code, JS moves all function declarations and variable declarations to the very top of the scope, but in your case, you're not simply defining a function, or declaring a variable: JS has to do something, too: assign a reference to a variable. The function won't be hoisted:
var foo = function()
{
console.log('foo');
};
foo();//logs foo
foo = function()
{
console.log('bar');
};
foo();//logs bar now
If foo were undefined prior to the assignment, you'd get an error. If any code preceded the code above, JS would hoist the variable declaration of foo, but it's value would still be undefined.
What's the point? This will prove useful when you start playing with closures, or if you need the function to differ, depending on a branch (if (x){ foo = functionX} else { foo = functionY;}). These are just 2 reasons why you'd want to avoid scope hoisting... but the most important reason of all ATM has to be redefining a function on the fly
Note that in processing.js (as used by this Khan academy demo), the function draw is automatically called every frame reference doc.
This bit of code overrides the default (empty) implementation of draw so that the given code is called every frame.
Khan academy has a tutorial about this use of the draw function here.
function draw(){ return "Sample"; };
var draw = function(){ return "Sample"; };
are same meaning.
function () { ... } creates a function value. That is, something that can be passed around just as easily as a number, or any other object in javascript.
He then binds it to the name draw for future reference.
He could as well have written
function draw() {
...
}
For these purposes they are equivalent.