开发者

Javascript () operator invokes function [duplicate]

This question already has answers here: Wh开发者_StackOverflow社区at is the (function() { } )() construct in JavaScript? (28 answers) Closed 7 years ago.

I have been using javascript for a while now and am starting to realise how badly I have been using the language. Some more advanced aspects of it are comming to light such as closures, module pattern etc.

Can someone explain how the () operator works when placed at the end of a function i.e. why does it immediately invoke it - i havent seen this before and am puzzled as to how this actually works.

as in:

var myFunct = function() {
    alert("here");        
}();

The () at the end will immediately invoke the function.


A function is an object. Using function_name refers to the actual function object. And function_name() refers to the result of the function. For example:

function foo() {
  return 2;
}

typeof foo()
= "number"

typeof foo
= "function"


Javascript functions are first-class objects. They can be stored, passed and returned. Since they're functions, they can also be called.

So you can write this:

var f = function(message) {
    window.alert(message);
}

f("Hello, world!");

That creates an anonymous function object and stores it into f. Then it calls it through f().

You can also create an anonymous function object and call it immediately without storing it in a variable:

(function(message) {
    window.alert(message);
})("Hello, world!");


The () construct means "function call". The thing about JavaScript that's different from some other languages is that identifiers are not the only thing you can call as a function. So from C, something like this might look familiar:

fnName();

But in JavaScript, any expression can evaluate to a function, which means it can be called as a function call. Like so:

(function () {/*do something*/})();

The parentheses around the function expression are necessary to group expressions so that the second set of parentheses is a function call on the expression in the first set of parentheses.


That's simply the syntax for invoking a function:

function foo() { alert('Purple is a nice colour') }
foo();    // Invokes the 'foo' function

Similarly, since in Javascript functions are first-class objects, one can do:

var foo = function() { alert('I like camels') };
foo();    // Invokes the function that the variable 'foo' has a reference to

This can even be expressed without using an intermediate variable (since a function is an object):

(function () { alert('Ponies are cool') })();    // Creates a function object, then invokes it


In JavaScript, functions are objects too, and by applying the () operator to it, you will invoke the function and the invocation will evaluate to the result returned from the function.

As such, let's break down your statement, which is:

var myFunct = function() {
    alert("here");        
}();

First, you define a function, so let's "refactor" this so that part becomes clearer.

var myFunctionDeclaration = function() {
    alert("here");        
};
var myFunct = myFunctionDeclaration();

Now, it should be easier to see that you're invoking the function in your code.

Function declarations aren't statements that need to be by themselves, but can be used as expressions that return the function object.

So basically your code was this:

var myFunct = (expression that produces function object)();
                                                        ^^
                                                        +--- invoke the function

This means that you can chain this together. If your function returns another function, you can call this new function as well, in the same statement.

For instance:

var myFunct = function() {
    alert("here");
    return function() {
        return 10;
    };
}()();
 ^ ^
 | +-- calls the inner function, that was returned when calling the outer
 |     function
 |
 +---- calls the outer function, which returns a new function object
// myFunct ends up being 10


If () didn't invoke the function, then some other syntax would have to. It's just a choice of syntax for a function call, chosen for its familiarity from many earlier languages. The arguments, if any, go in the parentheses.

It's hard to see how you could have done anything in Javascript without encountering function calls.


I assume that you mean an anonumous function that is executed immediately (and according to your edit, my assumption was right):

(function(){...})();

It works for any value that references a function, for example:

var x = function(){};
x();

function y(){}
var z = y;
z();

Or even a function that returns a function reference:

function a() {
  return function(){};
}
a()();


It's not so much that the function is being invoked (although in practice it is) but that arguments are being passed to the function and the function is being evaluated.

In the case of self-invocation I admit it does get confusing. But here's a break down of what's happening. Say I make an anonymous function assigned to a variable.

var myFunction1 = function () { 
console.log("function assigned to variable object myFunction1"); 
};

The reason it is allowed to be an anonymous function is because it is stored in the variable myFunction1 turning it into the object with the property myFunction1 and the function expression that was assigned to the variable as the property value.

In essence we have var myFunction1 rewritten to global = { myFunction1 : (function () { return 1+2; })(); }

I don't need to name the function in the same coding pattern as I would for a function not assigned to a variable because I can call it via the variable name as a variable is an object. This is important as we rely on the concept that almost everything in JS is an object that are defined as a multitude of object types (i.e. functions, variable names, booleans, numbers, symbols and more).

function () { 
    console.log("function assigned to variable object myFunction1"); 
};

This won't execute because the expression isn't assigned as an expression. It is now being declared because you started with the keyword function telling the interpreter I'm declaring this function. But you have to give a name in all function declaration for interpreter reference. So (); when ran has nothing to go off of. There's no object or parameters to evaluate, you didn't name the function either so there's no reference it's simply a ghost function. Think of it in the form of dot syntax where you can access an object properties via object . property

The parenthesis wrapping the function are now a parameter (function (){}) of the anonymous execution. That parameter is simply shorthand that says this is a expression. Then you access the parameter by executing () with the caveat that since I've accessed the function I'm now in the function and can access any params in that function.

(function (a){})(a);
//Opening the initial parameter which is a function and then internally accessing the function params.

(1+2); 
//Will evaluate to 
3
(1+2)(); 
//Will not run because I've not only accessed the param of the expression but I've now told it to evaluate the internal expression in that param and there is none

(function () { return 1+2; })(); 
//Will run because I've accessed the initial param, which is a function and asked it to execute it's internal expression in the braces return 1+2 

In essence the interpreter is running a boolean. The questions are: 1) does the parameter exist? Yes 2) Is there an internal expression? No, because it is not a function

This is why ! is also used in anonymous function declaration, i.e. expression writing.

! function () { console.log("This is true and ran the expression" }();
//Is it not a function? True
//Evaluate the expression since it is not a function

function () { console.log("This will never log because it is not true" }();
//Is it a function? False
//Do not evaluate the expression since it is false

Now the we know that, the reason that () can't defined solely as an invocation operator, while in basic assumption may make sense, is because it serves in a several capacities dependent on the coding pattern, let's move on.

When stating the parameters/arguments of an function you use () also.

function myFunction2 (a,b) { sum = a+b; console.log(sum) };

In this example we have used () to defined the parameters/arguments of the function to include a & b which we will then reference later in code. These are similar to variables defined in script but with the fundamental difference of being able to pass argument definitions to them while not assigning values remember when you assign you store. This seems trivial when you could re-assign values to variables at any point but in practice we are looking to gain the simplest form of execution. That's why this exists, along with another core concept of hoisting which will be briefly discussed later.

Reassigning values would simply be a waste of time and foreseeably cause innumerable errors in coding (due to scoping issues and others such as hoisting that we won't get into) along with additional processing not needed. Remember, every coding language is built to solve an issue and their further versions and iterations are with the intent to make the solutions even more efficient and to also accommodate new methods and structures also(which we also won't get into for the sake of this question).

So we now know that () isn't necessarily a singular method of invocation but is a multi-method which allows the declaration and assignment of the declarations in JS coding.

Now let's look at an anonymous function:

(
    function () { console.log( "My anonymous function is not assigned to a variable");
    }
)
();

What have we done here? Well it's simple in essence the function is wrapped in () which we now know has the power to both declare and call then assign values to an argument. So we have 2 parameters of this function actually. The first is the function which is anonymous so there is no name we can use to call or invoke this function. Then we have () after the word function which contains no parameters (which you can add parameters if wanted into).

Now here's a caveat of anonymous function declaration. It is only an expression! We know that expressions are only a group of numbers, symbols and operators that are grouped together to evaluate and show a value. Such:

1 + 2 = 3; //This is an expression 
function (b) { b = 1+2; console.log(b) }(); //This is the expression of 1+2 which is 3 and then that value is assigned to b

The reason this is important to know because an expression is far different from an object. With objects they are stored, can be called and manipulated. An anonymous function, even if named, is still just an expression. It will never convert in to an object. For instance:

( function anonFunction (b) { b = 1+2; console.log(b) } ) (); anonFunction();

Will result in 3 and anonFunction is not defined. This is because the function was just a self-running expression meant only to express a value for that instance. The interpreter doesn't log this function this as an object. For that you would need to assign the expression to a variable which in turn makes the variable an object that contains the expression anonFunction.

var myDefinedFunction = function (b) { b = 1+2; console.log(b) }; 
myDefinedFunction();

You'll notice the outside and end parenthesis are removed. They are not needed and will cause an error because we don't want the function to be just a self-running expression. We want the function to by assigned to an object. In real world application the most efficient way is to assign the function with a name. They in fact both produce the same value of the object. Both the var and function contain the function's expression:

(b) { b = 1+2; console.log(b) };

The core difference here is scoping and hoisting. Let's discuss hoisting first. Before any code is ran all the functions are hoisted to the top. Then any variables that are referenced to before being defined but are in the code are hoisted but the defined values are not. The value is only assigned when encountered. So creating a named function takes precedence over any other function, including the function expressions that are non-anonymous.

myFunExpression;
myHelloFun();
var myFunExpression = function () { console.log("hello") };
function myHelloFun () { console.log('Hello from function') }

You'll get "Hello from function" and undefined for this because the var value was assigned after the var execution/call. Also you can't use () with the variable because the variable itself is not a function, it contains a function. So you can't evaluate the variable because there's no expression to evaluate or arguments to pass in the expression for evaluation purposes.

Since you can't use () with execution of the variable. Scoping in the sense of passing arguments to the function also cannot be done. It's usefulness is only for calling an expression already assigned to the variable. The only way an argument can be passed is if it's already in the function expression and that parameter/argument is able to fetch the parameter in the scope availability of the function.

So to summarize this exhaustive explanation. The () operator is a parameter/argument holder and an evaluation/execution operator dependent on the coding pattern. It is not simply used for invocation.

When used in anonymous functions:

(function (a) { return a; } ) (2 + " hello");
//The value "2 hello" string is passed for evaluation return the value

(function (a,b) { return b; } ) (2 + " hello", "my b value");
//The value "my b value" is passed to the 2nd parameter for evaluation

(function (a,b) { return b; } ) ();
//undefined because the evaluation of return has no passed arguments
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜