first of all sorry if I'm not posting on the right place or if there's already a duplicate, but i don't know what to call this or how to search for it.
Can someone please explain to me what does the following code mean:
function noisy(f) {
return function(arg) {
console.log("calling with", arg);
var val = f(arg);
console.log("called with", arg, "- got", val);
return val;
};
}
noisy(Boolean)(0);
// → calling with 0
// → called with 0 - got false
Why do I need to have (Boolean) after the function call ?
noisy(Boolean)(0);
What do i call this type of function call ?
Thanks in advance!
This is tricky stuff. (Boolean) might throw you off here, but really it's just a regular old parameter. You could replace Boolean with any function, like doStuff, and it'd still work.
And yes, as you pointed out, this is a duplicate question. You're looking at something called "closure." Here's a fantastic answer from StackOverflow:
How do JavaScript closures work?
"noisy" is a function that returns a function if you call it.
By passing Boolean into the function, Boolean is called like Boolean(0) which results in false since 0 is a falsy value.
Boolean is just a constructor that you can use to create booleans or to cast any value to a boolean.
You are calling a function noisy(...) which is returning another function which it constructs using information from its parameters. The function call noisy(Boolean)(0); is actually two function calls and could (maybe should) be written as:
var noisyFunction = noisy(Boolean)
noisyFunction(0)
The fact that noisy() takes a function (Boolean is a function MDN). Has no real effect on the syntax being used here, it could take no arguments, or something less zany.
Your selection of the higher-order-functions tag really kind of sums it up. This is an example of programming with them. The fact that the value f is available to noisyFunction after noisy returns is the result of a closure (MDN). Some programmers might then describe this as, "using a closure", but it is not specific to the pattern shown.
You need to pass an f - it could be anything else than the Boolean function. Try
const increment = x => x+1;
const noisyInc = noisy(increment);
console.log(noisyInc(1));
In your original code, the intermediate variable is omitted - just like I could've written noisy(increment)(1) here.
Related
I am new to Javascript and sort of working through the weeds on these ternary operators. I have this small code segment:
const x = MSys.inShip ? 'ship launch' : '';
if (x != '') {send_command(x);}
While this works efficiently enough I am curious as to if it can be rewritten inside of the function call. Something like the following:
send_command(const x = MSys.inShip
? 'ship launch'
: MSys.alert("You aren't in your ship!);
This may not make sense with the current example but it's the best idea I had at the time. Basically, I like the shorthand of the ternary style for easy if/then conditionals but I don't like how it's tied to a variable which must then be called. I'm looking for a way to use that shorthand without having to tie to a variable.
Finally, the purpose of this is to see if you are in the ship and if you are, launch. If you aren't don't do anything at all or just send an alert message.
I am curious as to if it can be rewritten inside of the function call.
Yes, it can. But, if you do it there, then there is no need for a variable. You would be passing the function's argument directly inline.
Having said that, you can't pass that MSys.alert() statement as the "else" value because it will be executed in all cases. You'd have to pass a value there that the function can use as its input argument
send_command(MSys.inShip ? 'ship launch' : 'some other string');
Here's an example:
function foo(x){
console.log(x);
}
// If a random number is even, pass "even". If not, pass "odd"
foo(Math.floor(Math.random() * 10) % 2 === 0 ? "even" : "odd");
An important distinction between your two approaches - The second approach will ALWAYS call send_command() whereas your first approach will conditionally call it.
This distinction will matter depending on your implementation of send_command, but it sounds like you want the behavior of the first approach.
Additionally, You can't declare variables using const in a function call. If you just pass in the ternary operator, you will end up calling send_command with either your string, or undefined (the return of calling alert() ).
However, as an answer to your question, yes you can pass the ternary operator to a function like any other value. The ternary operator is an expression that will return a value.
Technically, you could keep a variable (such as operation) below, which references which method you want to execute, depending upon some conditional. And then you could pass that variable method the variable string it should get.
So, as you can see, it can be done. But look at how much complication was added to the process, rather than just using a simple if else statement.
function test_logic ( inShip ) {
// if they are in their ship, the operation should be the send_command method
// otherwise it should be the window alert
var operation = inShip ? send_command : window.alert;
function send_command ( command ) {
console.log( command );
}
// give the operation the desired string
operation( inShip ? 'ship launch' : "You aren't in your ship!" );
}
console.log( "Not in ship test" );
test_logic( false );
console.log( "In ship test" );
test_logic( true );
I don't know if I chose the right title for this question, and maybe this is why I cannot also find an answer to this question.
While reading a javascript book, I found this example while talking about closures.
function multiplier(factor){
console.log('factor:'+factor);
return function(number){
console.log('number:'+number)
return number * factor;
};
}
var twice = multiplier(2);
console.log('twice:'+twice(5));
And in console I get this output:
factor:2
number:5
twice:10
I understand what a closure is meant to be, but I do not understand how the variable number, that by my knowledge I expected to be undefined, get the value 5.
My reasoning is the following:
When I call the function multiplier(2) the local variable factor is assigned the value 2, so the first output is correct.
But when it reaches the line return function(number){ it shall assign number undefined, since no value has been previously assigned to such a name.
So it shall crash at all, and not doing correctly the output I got.
May anyone help me understand why calling twice(5) it get the output
number: 5?
Thank you all, excuse me again If i did not post the question in the right way, feel free to modify anything to make this question more intelligible.
return function (number) { ... } returns a function. number is not a variable, it's a function parameter. The same way that factor in function multiplier(factor) is a parameter. It is neither undefined nor does it cause anything to crash either.
In essence, multiplier(2) returns this function:
function (number) {
console.log('number:' + number)
return number * 2;
}
...which you assign to twice, so twice is now the above function.
I think the key thing that you're missing here is that the returned function acts just like any other function. The function isn't entered until it's called.
return number * factor;
doesn't run until you call twice. It's just like how
console.log('factor:'+factor);
doesn't run until you call multiplier. The body of the function isn't entered until the function is called. number doesn't have a value until twice is called, but the code that uses number also doesn't run until twice is called.
But when it reaches the line return function(number){ it shall assign number undefined, since no value has been previously assigned to such a name.
Here's the misunderstanding. Remember: In Javascript, almost everything is an Object. Some will say that many things that you interact with regularly (strings, numbers, booleans (Notice how I put these types/primitives/words first letter in lowercase. I usually use uppercase for Classes and lowercase for primitives)) are primitives, not objects. This is true, but for the purpose of this thread let's consider (almost) everything is an Object.
Let's get back on this sentence you wrote:
when it reaches the line return function(number){ it shall assign number undefined
Here's the issue: when it reaches the line "return function(number){}", it actually returns a function, which is an object.
It does not execute this function, it only declares it, and returns it, as an Object.
You could have wrote "return 666", it would have returned an Object. A Number.
Let's continue.
Your variable "twice" now contains a function. Guess which one. This one:
function(number){
console.log('number:'+number)
return number * factor;
}
Remember, you've declared it and returned it in only one statement:
"return function(number){...}"
Your "twice" variable is now equivalent to a named function you could've declared this way :
function twice(number){
console.log('number:'+number)
return number * factor;
}
Yes, functions are Objects, named functions are like named variables, and variables can be functions.
You can call it this way for example: twice(9), or this way: twice(5).
That's what you've done.
Now let's answer your question:
why calling twice(5) it get the output number: 5?
Because:
var twice = function(number){
console.log('number:'+number)
return number * factor;
}
And you've executed "twice(5);" which in turn executed console.log this way:
console.log('number:'+5);
As far as I've understood, in your "function multiplier()", you do not want to return a function but rather the result of this function itself. I advise you to read about IIFE (Immediately-invoked function expression).
With this you will be able, in only one statement, to:
- declare a function
- execute that function
- (and eventually return its result)
Have fun playing with Javascript. Javascript is great, only when you know what's going behind.
Is there way to create a new global method where I can have variable.myMethod() and it return true or false? Basically, I want to check to see if the variable is undefined and instead of using typeof(variable) == 'undefined' or specifying a function, is it possible to do something like variable.isUndefined() and it would return true or false?
I'm going to go ahead and post this as an answer, so I can go into a bit more detail.
As I mentioned in my comment, you have to be extremely careful about the terms that you use here, as undeclared and undefined mean two very different things.
If a variable is "undeclared", it doesn't exist, thus you cannot attempt to call any methods that might exist on it if it were declared.
If a variable is "undefined", it exists, but it doesn't have a value assigned to it. When this is the case, you can attempt to call methods that may exist on it, however the chances are that they'll fail, since variable doesn't have any value.
Every type in JavaScript is a child of the Object type, therefore you add a method to them, like follows:
Object.prototype.myMethod = function() {
console.log("This is my method");
};
So, in theory, you could create a method to check to see if a value exists, and return a true/false value.
Similarly to what StackOverflow user Barmar pointed out, undefined and null are not children of the Object type, thus your method will not exist.
As other comments have stated, you're probably better of sticking with something like follows:
if (!myVariable) {
// myVariable doesn't have a value
}
I'd like to point out that most of my explanation was unnecessary, as user Barmar pointed out, there is no practical difference between undeclared and undefined.
If a variable is undeclared, it's "value" is essentially read as undefined, thus your method will not exist.
this is a paradox. you can never have a method inside an undefined object because and undefined object does not have anything at all. to make it clear imagine this object
var a = {};
a.b is undefined here, so trying to call a.b.isDefined() can not work because you dont even have b. to make it work you need b defined like this
var a = {b:1,isUndefined:function(){return false}}
so you have to make a generic function that takes objects. This will do the trick
function isUndefined(obj,stringLink){
var arrayLink = stringLink.split(".");
var current = obj[arrayLink[0]];
if(!current)return false;
for(var i =1;i< arrayLink.length;i++){
current = current[arrayLink[i]];
if (!current)return false;
}
return true;
}
it will more or less check for nested object until it reach the target.
if you have
var a = {b:{c:{d:{e:{f:1}}}}}
//this function will do a["b"]["c"]["d"]["e"]["f"]
isUndefined(a,"a.b.c.d.e.f") //gives true
//or you can use
if(a&&a.b&&a.b.c&&a.b.c.d&&a.b.c.d.e&&a.b.c.d.e.f)//lots of work here
using prototype method we can create new methods... like...
Object.prototype.newMethod=function(){
// do something
}
Here I am defining the newMethod with an anonymous function... now if I want to use this method, I have to use it like: <object>.newMethod();
But now I want to create a new method which I can use like: <object>.newMethod;... no brackets... How can I do that...??
please don't use any jQuery...
Erm, you can't. To call a method, you write parentheses after it. Otherwise you're just referencing it.
The only exception to this rule is when you write something like new Date, where the parentheses are implict due to the new keyword and only because there are no arguments given.
I can't really understand why you would want to do that, but it is possible, albeit with a nasty hacky workaround. What you're actually looking for, AFAIK, is a magic property (like the someArray.length property).
var foo = {val:'foo'};
foo.length = (function(that)
{
return function()
{
return that.val.length;
}
})(foo);
//at this point foo.length(); returns 3, but still requires parentheses
//so, build another closure, and assign a valueOf method to the lenth method:
foo.length.valueOf = (function(method)
{
return function()
{
return method();//call the length method
}
})(foo.length);
console.log(foo.length +1);//logs 4
foo.val += 'bar';
console.log(foo.length);//logs 6
//BUT:: be carefull!!
alert(foo.length);//coerces to string, we haven't redefined the toString method, so the function code will be alerted
alert(foo.length + '');//alerts 6
This is just to show you that, yes it is theoretically possible, but please, please, don't use this kind of overly polluted hacks... I haven't thoroughly tested this, but ATM, I've already noticed that console.log(foo.length); can return a different value, not sure why, yet:
foo = {val:'foo'};
foo.length = (function(that){return function(){ return that.val.length;};})(foo);
foo.length.valueOf = (function(method){return function(){return method();};})(foo.length);
foo.length;//returns 3, great
foo.val += 'bar';
console.log(foo.length);//logged 3 at first, now it's back to logging 6!<-- don't trust this is the conclusion
The only way to call a function without parenthesis would be to define it using getters and setters.
Note these are new to JavaScript 1.8 and are not supported by all browsers.
I was gearing up for Javascript, reading the tutorials at W3Schools and came across this code:
function sortNumber(a, b)
{
return a - b;
}
var n = ["10", "5", "40", "25", "100", "1"];
document.write(n.sort(sortNumber));
It sorts the elements in the Array, pretty simple. But how can we pass sortNumber ( a function name) as a parameter to the sort function?
The original example
But how can we pass sortNumber ( a function name) as a parameter to the sort function?
Functions are first-class objects in JS and can be passed around as parameters or variables. Are you clear how the sort itself is working?
Surprisingly, JavaScript has its roots in a language called Scheme.
Scheme allows certain functions (called 'lambda functions') to be passed around as though they were a variable.
JavaScript handles functions in much the same way scheme did. (Some people say that "functions are first-class-citizens in JavaScript.")
For example, you can write:
// Assign a function to foo
var foo = function () { alert('bar'); };
// Call foo like a function
foo();
The result would be that the message 'bar' is shown.
The classic example of lambdas is the "Adder" example:
adder = function (x) {
return function (y) {
x + y
}
};
add5 = adder(5);
add5(1); // == 6
Hope this helps.
If you look at the documentation for the sort function within Javascript, the parameter that it accepts, which is optional is a function that can be used to determine the sort.
The function returns a positive, negative or zero value allowing the sort function to determine where everything needs to go.
You're actually passing a reference to the function itself, not its name. If you were passing its name, you would enclose it in quotes like this: "sortNumber".
sort() (as the documentation says) takes an optional argument which specifies the sorting function.
Functions are first class citizens in javascript.
Sort can take an optional paramater, a function that returns a -1, 0 or 1(whether a greater, equal to or lessthan b)
Using a-b returns a positive, zero or negative number, to do this.
The answer is available on W3Schools as well :
http://www.w3schools.com/jsref/jsref_sort.asp
the Array sort() method takes one parameter which is a function handler.
A variable in javascript can contain a anytype of value, that includes functions. If you use the name of the function without the parenthesis, your referencing the function, and not actually calling it.