JavaScript methods, calling method without parentheses - javascript

Hello there I have a question with the that I need some help with to increase my knowledge and understanding of JavaScript.
Within my init method please look at this particular line with the .on method where I am saying when button is clicked we’re going to refer to the contactForm object by using the this keyword and then we’re going to call the .show method.
.on( 'click', this.show );
Now the question is – if show is a method, then why aren’t we doing this, why aren’t we calling the method like this?
.on( 'click', this.show() );
Am I correct in saying it’s because we don’t want to call the show method immediately, if JavaScript came across the init method would parse all of this code, and then it would come to this section right here – this.show() - and it would immediately execute this function. But I don’t want it to do that, I only want that function to be called on the condition that the corresponding button is clicked.
When the show method is written as this.show does the absence of the parentheses stop the show method from automatically executing ?
var contactForm = {
init: function() {
$('<button></button>', {
text: 'Contact Me!'
})
.insertAfter('article:first')
.on( 'click', this.show() );
},
show: function() {
console.log('showing');
}
Sorry if I haven't been descriptive enough or accurate enough with my terminology. Any succinct and clearly explained answers would be massively appreciated.

Yes, what you are describing is correct, however, you're looking at it the wrong way.
It seems, as if you regard function names without parentheses to be some sort of special case, but in reality, it's the other way around.
It is important that you understand the concept of expressions and operators.
Operators
() is a regular operator, as is - for example, which negates a value. Operators are always applied to values: -5 negates the value 5, -(-5) negates the expression (-5) which is 5 again.
() on the other hand tries to call the expression to its left as a function: expr().
Functions are values
Functions in JavaScript are values that you can pass around just like you can wit the value 5:
var five = 5;
var returnFive = function() { return 5; };
var five2 = five;
var returnFive2 = returnFive;
alert(five2);
alert(returnFive2());
There's really nothing more to it: functions are just values, that happen to support some special magical () operator that "calls" them.
For this reason, it's perfectly valid to do any of
show()
(show)()
((show))()
etc, because (expr) simply evalutes to expr.
Evaluating expressions
Operators take one or multiple values, operate on it, and yield some other value:
4 // No operator, expression evaluates to 4
4 + 4 // This expression evaluates to 8
returnFive // No operator, expression evalutes to the function value
-5 // Unary operator, takes one value, negates it
returnFive() // call operator, executes the function, evaluates to its return value
What I hope you take away from this is, that functions aren't that special, there is no intrinsic connection between show and that pair of parentheses.
When the show method is written as this.show does the absence of the parentheses stop the show method from automatically executing ?
Yes and no – This suggests that show without the () is a special case to be handled separately, but that's not true. It's like saying "-5 is more normal than 5" and the absence of - makes something a positive number. It's the other way around, however: 5 is the "default", if you will, and -5 the special case. It's the same thing with show.
Applying this to your example
The on() function expects to be given some sort of callback, i.e. a function. If you pass show(), what are you passing? The evaluated expression show(). What is this? Whatever show() returns, of course. As such, on() has "no idea" that you have done something with show(), all it gets is some value without a connection to show().
Of course, the show() function might itself return a function, because, as we have learned, functions are just values like 5 and "foo" that can be passed around.
In that case, the on() function is still being passed a function which will be called on the corresponding event.

You are correct. When you reference a method (or any function, actually) without adding the parenthesis, the runtime will interpret that as a function reference.
So, on your example, you're effectively passing the show function to the on function, so that it can be executed later. Functions that receive other functions as parameters, or that return other functions as result are called "high-order functions"

Related

Javascript ES6 fat arrows empty parameter f instead of ()

I've noticed that when creating functions in Java Script ES5 you can specify parameters that will not necessarily have to be used, e.g.
function foo(uselessParam) {
// code that will not use uselessParam
}
If I'm correct - if I wont use this parameter within my function I can call that function without passing that parameter and "foo" will still run without throwing errors. This gave me idea to use fat arrows in ES6 like this:
let foo = f => {
// code not using f parameter
}
"f" in my opinion points that this piece of code is a function in more intuitive way than "()" I like doing so, even that "()" suppose to be used when no parameters are specified.
Here is my question: is there any scenario when using empty parameter instead of no parameters passed at all could be a problem? Could using this pattern cause any problems? What do you think?
The function will have a different .length, so if any introspective code is using that property for anything, you may see unexpected results.

Javascript anonymous functions with parameters. Where are those parameters defined?

I had a doubt about replacing some characters in a textbox using jQuery and I landed in this question. The accepted answer suggested something like this:
$("#mySelector").val(function(i, v) { //i, v... where they come from??
return v.replace("#","Custom Text");
});
That works fine but I still have the same doubt. Those parameters, i and v. Where do they come from and how they are filled with data? They are not declared anywhere. How do i and v in this case, has the data that I need?
These answers talk about it, but it seems just an overcomplicated explanation for what should be, an easy thing to explain.
So, the question is simple. How in the world those parameters in the anonymous function, get filled with data. Where do they come from if I didn't declare them anywhere?
They are set when the jQuery library calls the callback. Note that you are passing a function as a parameter into the $.val function. The $.val function passes values to the function that you passed to it.
Here is a simple example of how callbacks work:
function coolFunction(callback) { // accepting callback
// extra processing here
callback(1, 2); // calling the callback
}
coolFunction(function(a, b) { // passing function as callback
console.log('annonymous', a, b);
});
The jQuery function val checks the argument passed into it. When it finds a function, it calls it for every element contained in the selector, where i is the index of the element in selector, and v is the value... ie the element's value.

I've been told that functions no need returns can be called without "()" sometimes, Is that right?

some jquery code like:
$("#buy_price").blur(function(){
price_num;
});
$("#buy_num").blur(function(){
price_num;
});
function price_num() {
var price = $("#buy_price").val();
var num = $("#buy_num").val();
$("#buy_result").html(price*num);
};
can anyone tell me if it's right or not for sure?
better to use this way:
$("#buy_price, #buy_num").blur(price_num);
short and simple.
because price_num is a function itself then you can call it in the callback function of the bound event or you have to put () parenthesis there:
$("#buy_price, #buy_num").blur(function(){
price_num();
}); //------^^----if this way then its needed for sure.
No.
If you want to call a function, you can either:
Use ().
Instruct another function to call it.
The return value is irrelevant.
In this example:
$("#buy_price").blur(function(){
price_num;
});
The anonymous function is will be called by another function when the blur event occurs
The price_num function won't be called at all because neither of the two conditions apply
However, if you were to:
$("#buy_price").blur(price_num);
Then price_num would be called by another function when the blur event occurs.
This is not (entirely) true. The person that told you that probably got confused by a particular way of creating objects using the new operator.
This is valid and both statement will create an object as expected:
var a = new SomeFunction();
var b = new SomeFunction;
However, you can't call functions like that, as you are just returning the function to no-where.
myFunction; // Does nothing
Is exactly the same as these
42;
"Jsjsknsdjdj";
4 == 8;
All of these are just ignored because their value is not assigned to anything.
I'd recommend to always use () as it makes it clear when you read the code that a function call is being made, even when creating objects.

Only call constructor behaviour if particular function isn't called

Apologies - I have no idea to how to describe this. Example:
function OutputNumber(number) {
this.outputThisInstead = function (otherNumber) {
console.log(otherNumber);
}
console.log(number);
}
Desired usage:
new OutputNumber(1);
Console output: 1
new OutputNumber(1).outputThisInstead(2);
Console output: 2
Naturally, 1 will always be written to the console, irrespective of what else is called on the object.
I'm after this particular syntax, as well as the behaviour - attaching a function onto the initialisation. It feels impossible since the object must be constructed before any function is called on it, but is this achievable any other way?
It would be possible with a time delay (e.g., in a browser environment, setTimeout or similar) and a flag. Not desirable, but possible.
Without that, no, you can't base the action of the constructor on something that hasn't happened yet. You'd have to instead pass something into the constructor to let it know what was going on.
Browser example (again, I don't recommend this):
function OutputNumber(number) {
var handle = 0;
this.outputThisInstead = function (otherNumber) {
if (handle) {
clearTimeout(handle);
handle = 0;
}
console.log(otherNumber);
}
handle = setTimeout(function() {
console.log(number);
}, 0);
}
From your comment on the question:
This is the end of a sequence of chaining objects/functions, that I'm experimenting with. For example:
Assert.that(1).is.not(2).because('output this message if fails');
Here not(2) returns an object on which because can optionally be called. The behaviour of the object would depend on because being called.
Rather than have the behavior of an earlier function in the chain depend on a later function in the chain, I'd probably add an .end() at the end of something:
Assert.that(1).is.not(2).because('output this message if fails').end();
end would output whatever message/messages was/were stored by the previous functions. No need for black magic. Obviously this suffers from the fact that people could fail to put the .end() on, but you need some kind of trigger that it's okay to do the output, if you want the output to change based on an optional subsequent function call.
Not possible. By the time you do new OutputNumber(1) the function has already been called. A chained method will have no access to its preceding call.
It's possible to declare outputThisInstead as "static":
function OutputNumber(number) {
console.log(number);
}
OutputNumber.outputThisInstead = function (otherNumber) {
console.log(otherNumber);
}
new OutputNumber(1); //1
OutputNumber.outputThisInstead(2); //2
But if you want to create an object with the new operator the function will always log the number parameter.
You can also achieve similar behavior to the one you want with partial apply of the function (here). This is also called Currying or Schönfinkeling. The idea is that you can fill the function's parameters one after another and when the full set of parameters is available the function is being executed. You can see a currying example here.

Argument question javascript

One more question regarding arguments in javascript. I was reading a tutorial about the javascript framework Prototype and came over the following text, I will quote below:
"If you have some DOM methods of your own that you'd like to add to those of Prototype, no problem! Prototype provides a mechanism for this, too. Suppose you have a bunch of functions encapsulated in an object, just pass the object over to Element.addMethods():
var MyUtils = {
truncate: function(element, length){
element = $(element);
return element.update(element.innerHTML.truncate(length));
},
updateAndMark: function(element, html){
return $(element).update(html).addClassName('updated');
}
}
Element.addMethods(MyUtils);
// now you can:
$('explanation').truncate(100);
The only thing to watch out here is to make sure the first argument of these methods is the element itself. In your methods, you can also return the element in the end to allow for chainability (or, as practiced in the example, any method which itself returns the element)."
Everything seems pretty straightforward except one thing that I seem to have problem understanding. It says that you need to make sure the first argument of these methods is the element itself. And that is the case in the functions but when you call the function you only provide 1 argument? So for example:
$('explanation').truncate(100);
There is only 1 argument here that is sent to the function namely 100, but the function signature looks like this:
truncate: function(element, length){
So element comes from where? And is it logic that you must make sure that the first argument is the element itself but you do not provide it when you call the function?
Prototype provides two ways to do things:
Methods on the object itself, for example:
Element.toggleClassName('selector', 'something');
Via the prototype:
$('selector').toggleClassName('something');
IIRC, the second method simply calls the first, passing the Element selected to it as well as the original argument. That's what happens in your case as well.
Javascript functions can test their arguments and decide what to do based on what was passed. jQuery is famous for this and it's fairly common in a lot of libraries. It allows one named function to perform many different (but related) operations and often allows shorthand notation that can omit optional or default parameters. You can often pass one, two or three arguments and the code inside the function will examine which arguments are present and, in some cases, the type of the arguments to decide how to treat them.
When functions do this, you have to read their documentation carefully to see which parameters are required and which are optional and what order things can be passed in.
If a function optionally takes three parameters and all three are different types, it's possible for the function to examine the type of each passed parameter and accept them in any order. It can tell which is which by the type. I don't personally think this is good programming style, but it is possible. More likely, it allows you to just leave out some parameters which are not needed and the function will either adapt it's behavior when some things are missing or will set a default for that value.
In your specific example of truncate, I'd have to see a documentation page for that function to explain what it does when no element is passed vs. when one is.
Here's a made up example of a string truncate function that can be used a bunch of different ways:
var str = "This is a long string that I want to be truncated to something shorter";
str.truncate(10); // truncate to max length of 10
str.truncate("string", "end"); // truncate after the first occurrence of "string"
str.truncate(/\bbe\b/, "begin"); // truncate before the first occurrence of a regular expression
str.truncate("string", 10); // truncate 10 chars after the first occurrence of "string"
And the outline of this function would look something like this:
string.prototype.truncate = function(lookFor, pos, cnt) {
if (lookFor == undefined) {
return(this); // no parameters passed, nothing to do
}
if (typeof lookFor == "Number") {
// truncate to a certain length
} else if (typeof lookFor == "String") {
// look for a plain string
} else if (lookFor.exec) {
// look for a regular expression
} else {
return(this); // nothing to do
}
}

Categories