Binding function to another function in object - javascript

I try to bind a function but I dont really know how its work
For example
q={};
q.e=function(){return 1;}
q.e.i=function(){alert(this);}
q.e().i(); //Nothing happend I excepted that it will alert 1
So how does it work?
Thank you.

A function does also inherit from Object in Javascript. Hence you can assign properties to a function object, which you're just doing by calling
q.e.i = function() {};
but thats it. If you want to call it, you need to the same semantics
q.e.i();
in your current snippet, you're trying to execute .i() on the return value of e(), which happens to be the number 1.

You should be getting an error when calling q.e().i(); q.e() == 1 so (1).i() is an error since the Number object doesn't have an i method.
Hard to help since the code doesn't make any sense. I can only say that what you expected doesn't make sense in my head :)
Here's some code that would do what you expect
var q = {};
q.e = function() { return 1; };
q.e.i = function() { alert(this); }
// Call q.e.i, specifying what to use as this
q.e.i.call(q.e());
The trick is that in JS, this changes depending on how you call the function.
function a() {
console.log(this);
}
var obj = {
method: a
};
// Outputs the window object, calling a function without a `.` passes
// The window object as `this`
a();
// Outputs the obj, when you say obj.method(), method is called with obj as `this`
obj.method();
// You can also force the this parameter (to the number 1 in this case)
// outputs 1
obj.method.call(1);

Related

Call JS function with brackets

for my own personal improvement, I was fiddling with closures and functions in JS, when I found this behaviour that deeply puzzles me.
Take this function, assign it to a variable, and call it from two different HTML elements via jQuery:
var print = function(){
console.log("Hello" );
};
document.getElementById('element1').onclick = print();
document.getElementById('element1').onclick = print;
Why on earth is the second element, if clicked, to be the one that prints correctly "hello"?
I always thought you need to put brackets after a function's name to call it.
In fact, if I just call the function by itself (and not via a jQuery event) it works as expected:
var print = function(){
console.log("Hello" );
};
print; //does nothing
print() //prints "Hello"
What I am missing here? Is something related to jQuery?
Thanks in advance!
The difference is calling a function vs taking a reference to a function.
The syntax func() immediately calls the function provided. In element.onclick = func(), the event will be bound to the return value of func.
With element.onclick = func, you are not calling func, simply referencing it and assigning it to the event.
If func happened to return a function, then you could use the element.onclick = func() syntax, and it would do what you expect.
document.getElementById('element1').onclick = print(); // Assigns the *return value* of print
document.getElementById('element1').onclick = print; // Assigns print
function returnPrinter() {
return function print() {
// do stuff
}
}
document.getElementById('element1').onclick = returnPrinter(); // Assigns the return value, which is a function, thus doing what you want
(Too long for comment.)
If you really want to mess with your own head:
var print = function() {
return function() {
console.log("Hello");
};
};
document.getElementById('element1').onclick = print();
This will do what you expect, but perhaps not why you expect it to.
Using
document.getElementById('element1').onclick = print();
is equivalent to the value returned from print (but there is no returned value, so it is undefined)
document.getElementById('element1').onclick = undefined;
When the onclick event handler is called, it calls the assigned value expecting a function. undefined() will also give you the same error. print() will do what you were expecting, and that is why when you use this it works
document.getElementById('element1').onclick = print;
A function is just like any other variable, except it has an additional operator:
Just like with objects and arrays, you can use the dot and square-brace operators to retrieve their properties, you can use the call operator to call the function, but that function is still a variable nevertheless.
function a() {
console.log("potato");
}
var b = a;
b() //prints "potato" on the console
On your example, using the print function on its own (without the call operator did nothing, but that would be the same as if you wrote a number on its own: the result is the value itself!
console.log(a); //prints function a()
console.log(42); //prints 42
When you type a something on its own line, it's just going to return that value to the expression, but without anything to do, nothing happens:
a; //nothing happens
42; //nothing happens
Now, when you use the call operator, it runs your function and the expression's value is whatever the function returned, or undefined if it didn't return anything.
function doStuff() {
return "potato";
}
Now suppose you have this expression:
console.log(doStuff());
It will run doStuff, and return to the expression:
console.log("potato");
Then it will run console.log, with "potato" as its parameter, and it will do its magic to show on the console.
Events are just like that, saving a function to a variable to use later:
function doom() {
return Infinity / 0;
}
onDoomsday = doom;
//somewhere else in your code:
onDoomsday(); //destroys the world
you have to bind reference of a function to onclick but in first case you actually doing nothing other than calling a function:
document.getElementById('element1').onclick = print();
It will actually invoke the function print() and since function has nothing in return so it will not impact on element1 click event.
on the other hand
document.getElementById('element1').onclick = print;
In order to make first case working you need to return a function so it can be invoked on event:
var print = function() {
// when this will invoke it will return function
return function() {
console.log("Hello");
};
};
will assign reference of function to onclick event and it invoke the function on each click event.

What is difference between these two functions?

I have tried folllowing two ways of referring a function:
First
let a = function() {
somefunction();
}
Second
let a = somefunction;
Where somefunction is the following in both cases:
function somefunction() {
alert("hello");
}
Is there any difference between these two ways?
Yes, there is a difference between your two examples.
In the first case, you are defining a new anonymous (unnamed) function which calls somefunction. You are then assigning your new function definition to the variable a. a holds a reference to your new function.
In the second case, you are simply assigning your original function of somefunction to the variable a. The variable a then holds a reference to somefunction. You are not creating a new function as you are in the first case.
I think this example may make the difference clear. arguments is an array like object that contains each of the arguments passed to a function.
Try running each of these lines on your favorite browser console.
var somefunction = function() { console.log(arguments); };
Your first example demonstrates defining a named function a that closes around the named function somefunction.
var a = function() { somefunction(); };
Your second example makes a reference, b, directly to somefunction. This makes invoking b the same as invoking somefunction.
var b = somefunction;
Now if you call each of these a and b with some arguments you will see the difference.
=> a('a', 1);
[]
=> b('a', 1);
['a', 1]
In the first case the arguments object is empty. That's because the arguments that were passed to a were not forwarded onto somefunction.
In the second case the arguments are available to somefunction, because some function is being called directly.
Here is how you could redefine a so that it were functionally equivalent using apply
var a = function() { somefunction.apply(this, arguments); }
Running this at your console prints the argument array.
=> a('a', 1);
['a', 1]
var a = function(){
somefunction();
}
Is an Anonymous Function attributed to a variable.
somefunction :function() {
alert("hello");
}
Is an declaration of a function throungh the Object Literal notation.
The diference are shown when you are creating an object. The anonymous function are not acessible as a "public" method, instead in the Object Literal notation, that are acessible from outside.
As Douglas Crockford said, in JS the Good Parts, the first declaration are just a function and the second one could be a method.
In the first case, you are creating a function which calls someFunction(), then you assign that function to a, so now calling a() calls an anonymous function which in turn calls someFunction().
In the second case, a and someFunction become the exact same thing, calling a() is the same as calling someFunction().
The way you're setting var a by accessing the function is clearly out of scope.
So I suspect you have a typo : instead of = :
var somefunction = function() {
alert("hello");
};
somefunction(); // hello
...Now that your first and second makes sense with the code above:
Anonymous Function stored in variable:
var a = function(){
alert('Hey');
somefunction();
};
a(); // Hey // hello
Variable as Function Reference
var a = somefunction;
a(); // hello
In the other case than:
var objLiteral = {
somefunction : function() {
alert("hello");
}
};
var a = objLiteral.somefunction;
a(); // hello

How can I access what a function was called on?

I am assuming that $('thing1') or document.getElementById('thing1') will return the node or object representing <div id="thing1"></div> But how do I access that in myFunc()?
HTML:
<div id="thing1"></div>
JS:
var foo = $('#thing1').myFunc();
var myFunc = function() {
console.log(this); // I want to log $('#thing1')
}
I am trying to figure out how various api's work, take highcharts for example, they do something like this:
$('#dailyKPIChart').highcharts({
chart: {
zoomType: 'x',
spacingRight: 20
}
});
And the chart will load in $('#dailyKPIChart')
How does that work?
There is no way to (programatically) know which variable (or which function call) was used to get the object upon which a method was called.
A debugger will tell you (set a break point, and then look at the stack) but that won't be useful if you think you need to know the name in your code.
$a_jquery_object.selector will (in older versions of jQuery) hold the selector used to construct a jQuery object, which might help for your particular example.
And the chart will load in $('#dailyKPIChart')
How does that work?
It doesn't need to know about $() or '#dailyKPIChart', it only needs the object that you get when calling it, which is available through this, which your earlier example code already uses.
There are several ways to invoke a function in javascript and perhaps you are after call (or its cousin apply):
Supposing you define your funciton as:
var myFunc = function() {
console.log(this); // I want to log $('#thing1')
}
You can call it while at the same time you specify the context. For example, you can do this:
var foo = $('#thing1');
var myFunc = function() {
console.log(this);
}
myFunc.apply(foo);
Or via call:
var foo = $('#thing1');
var myFunc = function() {
console.log(this);
}
myFunc.call(foo);
If you have arguments to pass, you can do so by specifying an argument list or an array of arguments. For example:
var foo = $('#thing1');
var myFunc = function(one, two) {
console.log(one);
console.log(two);
console.log(this);
}
myFunc.apply(foo,[2,3]);
Or with call:
myFunc.apply(foo,2,3); //foo is the calling context
Fiddle

How to assign to members of a function?

Since functions are first class objects, it should be possible to assign to the members of them.
Am I right thinking that arguments.callee does this?
Are there any other ways to set these fields?
How is it possible to set field in first case?
function something1() {
arguments.callee.field = 12;
}
alert(something1.field); // will show undefined
something1();
alert(something1.filed); // will show 12
something2 = function() {
arguments.callee.field = 12;
};
alert(something2.field); // will show undefined
something2();
alert(something2.field); // will show 12
UPDATE 1
I mean how to access members from within function when it runs.
You don't need to use arguments.callee to refer to a function that has a name; you can just use the name. This is naturally the case when you declare the function using the
function name(...) { ... }
syntax; but even in a function expression, you're allowed to supply a temporary name:
(function temp_name(...) { ... })(arg);
So, if you want to set the properties from inside the function, you can write:
function something1() {
something1.field = 12;
}
alert(something1.field); // will show undefined
something1();
alert(something1.field); // will show 12
something2 = function something2() { // note the second "something2"
something2.field = 12;
};
alert(something2.field); // will show undefined
something2();
alert(something2.field); // will show 12
Here's how I would do it:
function something1() {
this.field = 12;
}
var test = new something1();
alert(test.field); // alerts "12"
test.field = 42;
alert(test.field); // alerts "42"
If you're going to treat it like a class, you need to create a new instance of it before you can access its fields.
JSFiddle
Am I right thinking that arguments.callee does this?
Yes it did, but now they deprecated it.
Are there any other ways to set these fields?
The official way to replace callee is to use an explicit function name, as in funcName.propertyName=.... This is however not always convenient, for example, with dynamically generated functions. To quote John Resig, we're going to miss arguments.callee, it was quite useful for specific tasks.
Simple
function something1() {};
something1.Property = "Foo";
You can directly assign the properties to any function just like a normal object. If to say in OOP language create static properties and methods.
Edit
The same inside the function
function something1() {
something1.AnotherProp = "Bar";
};
something1.Property = "Foo";

How the JavaScript this keyword works?

I have been doing some JavaScript development and I encountered this problem. Consider the following code
var obj = {};
obj.bind = function () {
console.info(this);
};
obj.bind();
I'm running the code on the FireBug JavaScript console. The expected result is that this displays a reference to the object in the console.
It actually displays undefined.
But, when I make this change to my code
var obj = {};
obj.bind = function () {
this.x = 'x';
console.info(this);
};
obj.bind();
Now the console displays the expected value of this, which is a reference to the obj object.
Why does this happen?
undefined is the return value of the function, which you'll get because you're not returning a value explicitly.
In both Chrome and Firebug, it correctly displays the Object in the console before the return value undefined.
So if you do:
var obj = {};
obj.bind = function () {
console.info(this);
return "foo";
};
obj.bind();
...you should see something like:
Object { }
"foo"
If Firebug is not displaying the Object when it is empty, you may need to check to make sure you're using the most current version.
In your example, "this" should be obj, just as some commenters pointed out. Here are the details that explain why --
In Javascript, the value of "this" changes depending on how you call the function:
When a function is stored as a property on an object, and you invoke that function by calling obj.foo(), "this" will be obj.
EX:
var obj = {
x: 1,
increment: function() {
this.x = this.x + 1;
};
obj.increment(); // Makes "this" be obj
When you invoke a function using syntax that does not refer to any owning object, "this" will be the global environment.
EX:
function someFunc(a, b) {
return a + b; // If you were to refer to "this" here, it would be the global env.
}
someFunc(5, 6);
When you invoke a function as if it were a constructor by using the new operator, a new object will be instantiated for you, and "this" will point to that new object.
EX:
function SomeConstructor() {
this.x = 42; // under the hood, a new object was instantiated for you, and "this" was set to it.
}
var result = new SomeConstructor(); // note the "new" keyword
// result will be { x:42 }
When you use call() or apply(), you can control what "this" is.
(No example here since it's fairly far from your question. Look up docs for apply() or call() for an example.)

Categories