I'm curious why:
(function () { return 'one' })()()
returns:
TypeError: (intermediate value)(...) is not a function
and not:
TypeError: 'one' is not a function
Error messages use variable names or other identities to say what is not a function. Because the return value hasn't been assigned to anything, it doesn't have an identifier, so the engine says intermediate value
The documentation of the error message "TypeError: "x" is not a function" explains:
What went wrong?
It attempted to call a value from a function, but the value is not actually a function. Some code expects you to provide a function, but that didn't happen.
It also provides some code examples that triggers this error and the actual error message reported by them. I won't copy them here but please take a closer look on them and notice the error messages they generate.
The "x" part is replaced in the actual error messages by the name of the object that is expected to be a function and it is not.
Because the object in this case does not have a name (it is an intermediate result computed during the evaluation of the expression, see the explanation below), the engine cannot report its name and tries to be as helpful as it can. It reports "(intermediate value)(...)" probably because this way it is more descriptive; it is a value returned by a function that is not stored but used for computation of another value.
It cannot report the actual value instead because the intermediate value can be anything; if it is a complex data structure then the error message becomes bloated without adding much information.
Apparently I didn't understand the question from the first time, what follows is my initial answer that explains why the error is generated, not why the error message is what it is and not what the OP expects.
This code ...
(function () { return 'one' })()()
... creates an anonymous function...
function () { return 'one' }
... calls it...
(function () { return 'one' })()
... then attempts to interpret the value returned by the function as another function and call it:
(function () { return 'one' })()()
The function created on step #1 returns a string ('one') when it is invoked (on step #2).
On step #3, the effect of the code is the same as calling 'one'(). This is not the same as one() (as you might think).
The intermediate value referred in the error message is the string returned by the first function call that is then used in the expression (as a function) without being saved in a variable (that's the explanation of the "intermediate" wording.)
As the error message clearly says, 'one' is not a function and attempting to use it as a function (by placing the second pair of parenthesis in the expression) doesn't work.
In order to make it work, the anonymous function created on step #1 must return another (anonymous) function, like this:
(function() { return function() { return 'one'; } })()()
Now, when it is called, the outer function returns an anonymous function that is similar with the anonymous function created on step #1 by the original code. When this function is called (the second ()) it returns the string 'one'.
This is probably not what you wanted. Calling a function given its name as string is possible only by using eval() which is language feature that is best to avoid (for several strong reasons.)
Because when in braces () it (function () { return 'one' }) becomes an expression which yields intermediate results and those results are not yet bound to a variable yet.
As per spec,
Specification type values are specification artefacts that do not
necessarily correspond to any specific entity within an ECMAScript
implementation.
Specification type values may be used to describe intermediate results
of ECMAScript expression evaluation but such values cannot be stored
as properties of objects or values of ECMAScript language variables.
Related
I’d like to know both for regular all-in-the-family JS developer-defined functions, as well as predefined DOM methods: what happens if I try to call IE’s attachEvent with the signature of the WHATWG’s addEventListener? For instance:
elem.attachEvent('onbillgates\'mom', function(e){ this.mount(); }, false);
Specifically, note the third argument false. Will that trip anything up, even though the attachEvent method’s signature only calls for two arguments?
What about this example?
function foo(FirstOf2, SecondOf2) {
console.log(FirstOf2 + SecondOf2);
}
foo(1, 2, true);
JavaScript doesn't have the concept of a fixed parameter list. For your own functions you can always specify as many parameters as you want and pass in as many as you want which ever type you want.
For built-in functions, which correlate to native code, it depends.
You asked on what it depends:
Let's look at the ECMA-262
Section 15 about built-in (not to confuse with host) functions in general
Unless otherwise specified in the description of a particular function, if a function or constructor described in this clause is given fewer arguments than the function is specified to require, the function or constructor shall behave exactly as if it had been given sufficient additional arguments, each such argument being the undefined value.
Alright. If I pass in less arguments than needed, it depends on the spec of the function itself (scroll down section 15 to find the spec for each built-in function).
Unless otherwise specified in the description of a particular function, if a function or constructor described in this clause is given more arguments than the function is specified to allow, the extra arguments are evaluated by the call and then ignored by the function. However, an implementation may define implementation specific behaviour relating to such arguments as long as the behaviour is not the throwing of a TypeError exception that is predicated simply on the presence of an extra argument.
Passing in too many arguments should never raise a TypeError. But still it may raise other errors. Again, it depends on the function you talk about.
You were talking explicitly about the DOM and not about built-in functions. To be honest I can't find the corresponding parts of the spec. The ECMA spec is so much easier to read then the w3 website.
Won't hurt. You can even call a function with less parameters than it takes, as long as the function code is ok with a few undefined values.
I came across this important, however old, question; and I hope it'll be beneficial for future generations to share my experiments with it:
One can use the arguments object in order to access a function's arguments, regardless of the amount of arguments in the function's signature.
It's worth mentioning that this doesn't apply to arrow functions:
function singleArg(x) {
console.log(arguments);
}
singleArg(1, 2); // Called with 2 arguments
singleArg(); // Called with 0 arguments
// Results in an error, as 'arguments' isn't defined for arrow functions
((arg) => console.log(arguments))(1);
It's stated in the documentation that arguments isn't exactly an Array:
“Array-like” means that arguments has a length property and properties indexed from zero, but it doesn't have Array's built-in methods like forEach() and map().
Hence the following code results in an error:
(function singleArg(x) {
console.log(arguments); // This line works
arguments.forEach(x => console.log(x)); // This causes an error
})(1, 2);
Upon calling a function with less arguments than in its signature, they're assigned undefined:
(function twoArgs(a, b) {
console.log(`a: ${a}\nb: ${b}`);
})(1);
Try taking a look at this post and perhaps this one.
From MDN:
The arguments object is a local variable available within all
functions; arguments as a property of Function can no longer be used.
You can refer to a function's arguments within the function by using
the arguments object. This object contains an entry for each argument
passed to the function, the first entry's index starting at 0.
You can use the arguments object if you call a function with more
arguments than it is formally declared to accept. This technique is
useful for functions that can be passed a variable number of
arguments.
function myConcat(separator) {
var result = "";
// iterate through non-separator arguments
for (var i = 1; i < arguments.length; i++) {
result += arguments[i] + separator;
}
return result;
}
I don't think it will mess anything up unless you are explicitly dealing with the implicit arguments array. Why are you doing this though?
I am new learner of Javascript and I got stuck in "functions returned from other functions".
The code is as below.
var createScream = function(logger) { return function(message) {
logger(message.toUpperCase() + "!!!")
}
}
const scream = createScream(message => console.log(message))
scream('functions can be returned from other functions')
scream('createScream returns a function')
scream('scream invokes that returned function')
Console output:
"FUNCTIONS CAN BE RETURNED FROM OTHER FUNCTIONS!!!" "CREATESCREAM
RETURNS A FUNCTION!!!" "SCREAM INVOKES THAT RETURNED FUNCTION!!!"
Question: why it will work this way? what is the process of executing?
Does function scream have any parameter? how does it work?
This may be very easy, I searched but no clear explanation.
Can someone please give me a hint or explain the whole execution process in details?
Thanks in advance!
First, Higher order functions are not about functional languages. Functions that operate on other functions i.e. taking a function as an argument and returning another function, are called higher order functions.
Your snippet:
You created an anonymous function with argument logger, which returns another anonymous function and bind that to variable createScream.
Then you called createScream with a function as an argument. storing the returned value in const scream. At this time you are returned a function with argument logger being the fat arrow function you passed.
Now you called scream with strings. Remember scream is also a function because in the earlier step the function call returned another function. That function has access to logger argument passed to the outer function. This is an example of closure.
When you call scream with strings. The returned function is called which is logging the message in uppercase plus !!!.
It will take sometime to get what is happening here, If you have limited programming experience. Read about higher order functions, lexical scope, closure.
In JavaScript and other functional languages, you will hear the term that functions are "first-class citizens" meaning that functions can be passed around as values or referenced by other functions.
It's normal for this to take a bit of time to grok, but try to walk through your code step by step and you'll get it:
The createScream function accepts a function as input (logger)
The createScream function then returns another function that accepts its own input (message)
The returned function uses the original input function (logger) as well as the second input (message)
And consider the execution order in usage as well:
scream invokes createScream with a console.log function
now when you invoke scream with a message, that message will first be changed as per the definition in createScream
then once the message is changed, it is invoked by the logger function console.log
I have just found that I can define a function in JavaScript like this:
function a(){ ([]()) }
and similarly, this way is also a valid function definition.
function a(){ ([]())()()([])([]) }
It doesn't even look like a valid syntax, doesn't it? But the compiler doesn't blame when define them. (Surely invoking a() will cause you an error later)
A function of an empty array? A function of a function of an empty array, or something? I can't even understand how this is considered valid to be defined as a function in JavaScript compiler.
In case you're curious: Not all these kind of function definitions will pass the compiler. You may try defining this below.
function a(){ ([]())()()([])([]){} }
JS compiler won't let you define it.
I know the function will not be able to invoke, but to my wondering, I can define it. So I'm eager to know why this is valid to define.
[] creates an empty array. It's not a function, so treating it as a function by calling it like []() will give a runtime error, but there's nothing syntactically invalid about it.
And wrapping stuff in parentheses, [] vs. ([]), has no effect when used on its own like that, but again it's valid syntax.
Try running a(), you will get a runtime error.
The thing is, when you define a function (like what you did), the function obviously won't be executed so any runtime error will not be reported (since the engine has no way of knowing a runtime error except by actually running the function).
EDIT:
In response to the author's comment, imagine this function:
function a(){ (alert()) }
which is syntactically similar to the first function. However this function is perfectly fine - no runtime errors.
That's why the engine allows you to define functions like this. In order for the engine to catch the problem in function a(){ ([]()) }, it has to make the inference "[] is an array, which is not callable, so this function generates an error". However, calling an uncallable object is a runtime error (TypeError) so the engine will not make the said inference - as that would be trying to catch a runtime error at compile-time.
P.S.: Calling an uncallable object is not necessarily a runtime error in other languages. In most strictly-typed language that is a compile-time error. If you do in Java int[] x; x();, that would generate a compile-time error.
As to the second function, you need to understand the concept of higher-order functions. If you don't know what that is, I will do a simple explanation here.
Imagine this:
function addone(x){return x+1;}
function f(){return addone;}
now if you run f()(1), that is equivalent to addone(1), which is 2.
Now f is a second-order function, you can define a third-order function:
function g(){return f;}
Then g()()(1) is again 2. If you want, you can define a hundredth-order function. Though in real code you rarely need more than second-order.
Now back to the second function in the OP:
function a(){ ([]())()()([])([]) }
You are trying to run [] as a fifth-order function, which is syntactically perfectly fine. Again, checking whether [] is actually a fifth-order function is a runtime thing.
Please note down.
1) A JavaScript function returns undefined (if there is no return statement define) even if there is nothing inside function.
2) Similiary ()()()([])([]) is valid. Because there is no any syntax error. Code inside functions are validated for syntax error inside validator e.g. there should be no code after () except semicolor ; or () etc. All type error will be validated only at execution.
3) This is valid but when you call this function, It will throw uncaught typerror
I was experimenting on alert but alert dosen't worked as i expected have look below lines:
var tobealerted = function(){return 'worked!'};
now when i alert this:
alert(tobealerted());
this will work fine! now
alert(tobealerted);
in this i removed parentheses. now it alert function(){return "worked"} not worked!
now i thought it may be a feature of javascript that it would alert any text without being in quotes then i wrote:
alert(worked!)
but the google console throw exception worked! is undefined , so my thinking was wrong. then again i wrote this
alert(function(){})
and you know what it alerted function(){}! and then i thought that alert would only allow such statement to be alerted without quotes. then again wrote:
alert(if(){}) //if is not defined
alert(for(){}) //for is not defined
alert(while(){}) //while is not define
but these did not worked for this i searched and found something, from my search i found this
functions are first class object
and according to wikipedia:
In computer science, a programming language is said to have
first-class functions if it treats functions as first-class citizens.
Specifically, this means the language supports passing functions as
arguments to other functions, returning them as the values from other
functions, and assigning them to variables or storing them in data
structures
so my question is
why did alert function only allowed function (){} to be alerted but not others
and if you think it is because that function is a first-class object then i don't think so because
i did not assign this function(last one) to any variable neither it returns anything in alert(function(){})
i am so much curious and also confused!
thanks!
You gave the answer yourself. Functions are objects and as such have toString() functions. The other examples you gave are statements, not objects.
As noted by others, window.alert() only displays String objects and triggers the toString() function of any other type of object. It expects anything you feed it to be an object or a reference to an object.
This is what happened when you were trying to alert those statements; it assumed if etc. were variable names, but it couldn't find any reference by that name.
alert converts its argument to a string. That's all.
> x = function() { }
function () { }
> x.toString()
"function () { }"
You can't invoke toString() on an if/for/while as those expressions don't resolve to values.
Function is just another type of object in Javascript, so:
alert(tobealerted());
alerts the function result but:
alert(tobealerted);
alerts the function object itself using .toString() method which returns function's body for objects of type function.
Statements like if and so on are not objects but full definition of function declares an object. So you can alert function and not if statement for example.
If you want the alert to return a value it must be in quotes like this:
alert('worked!');
If you want it to display a value returned from a function, it must be called as a function:
alert(tobealerted());
If you call a function without the parenthesis, you are basically asking for the definition of the function and because functions are first-class, it will allow you to assign it to a variable.
The if/for/while are conditional operators so they don't work the same as a user-defined function. They have a very specific use and aren't meant to be overrode.
When you tried alert(function(){}); it was no different from you trying to assign the function to a variable. The function definition was stored, but you didn't actually invoke the function. Now if you did alert(function(){}());you would have actually invoked the function and it would have alerted undefined. It is all a matter of defining vs invoking.
In my understanding defining a variable without the var keyword just evaluates to adding this variable to the window object. And on the other hand, trying to access a member of an object, that isn't yet defined, evaluates to undefined. So I can do things like this:
> foo = "bar";
"bar"
> window.foo;
"bar"
> window.bar;
undefined
Why am I not able to get an undefined variables value (undefined) when accessing it directly?
> bar;
ReferenceError: bar is not defined
There is another thing that I don't quite get, that I think could be related. When I type some literals into the console, they always evaluate to themselves. 1 evaluates to 1, [1] to [1] and so on. I always thought of a function to also be a literal because it has some value-like qualities (beeing first class citizen). But when I try to evaluate an anonymous function, I get a syntax error.
> function() {}
SyntaxError: Unexpected token (
I know that I can define a named function, but that evaluates to undefined (it defines the function somewhere rather then being it itself). So why arent functions literals?
thanks
For the first part of your question, see ReferenceError and the global object. Basically, explicitly referencing a non-existent property of an object will return undefined because there may be cases where you would want to handle that and recover. Referencing a variable that doesn't exist should never happen, though, so it will fail loudly.
For the second part of your question, you are trying to declare a function without a name, which isn't possible. There's a subtle difference between a function declaration and a function expression. Function expressions, for which the function name is optional, can only appear as a part of an expression, not a statement. So these are legal:
var foo = function () { };
(function () { });
But not this:
function () { };
If you just access 'bar', the scope is unclear. The variable is first sought in the local scope (if your inside a function). If it's not found there' the window object is checked. But any error you get logically refers to the 'bar' that doesn't exist in the local scope.
What would you expect to be displayed if you want to show a function like that? A function has no value and its declaration certainly hasn't. You could expect the console to be able to execute a function and return the result, but that's also dangerous. Not only can you have a function that doesn't return a value, but also, functions can contain code that modify their environment, in other words, running a function in the console could modify the current state of the document and the current Javascript state in it.
Javascript has been coded such that if you try to read a property of an object, you get undefined.
But, if you try to read the value of a variable that doesn't exist without referencing it as a property of the global object, it throws an error.
One could explain this choice a number of ways, but you'd have to interview one of the original designers to find out exactly why they chose it. The good news is that once you understand the behavior, you can code it one way or the other depending upon which behavior you want. If you know a global variable might not be defined, then you can preface it with window.xxx and check for undefined.
In any case, if you want to test if a global variable exists, you can do so like this:
if (typeof bar !== "undefined")
or
if (window.bar !== undefined)
Also, be very careful about assuming the console is exactly the same as a real javascript execution because it's not quite the same in a number of ways. If you're testing a borderline behavior, it's best to test it in the actual javascript execution context (I find jsFiddle very useful for that).