Explore why in JS, you need to add in front of the function!

Dachang Technology Advanced Front-End Node Advanced

Click on the top Programmer Growth Guide, pay attention to the official account

Reply 1, join the advanced Node exchange group

Introduction

We basically know that there are two ways to declare a function

function msg(){alert('msg');}//declarative definition function
Copy Code
var msg = function(){alert('msg');}//function assignment expression defines function
Copy Code

But there is actually a third way of declaration, the Function constructor

var msg = new function(msg) {
  alert('msg')
}
Copy Code

Equivalent to

function msg(msg) {
  alert('msg')
}
Copy Code

The method of calling the function is usually method name()
However, if we try to append () to the end of a “definition function”, the parser cannot understand it.

function msg(){
  alert('message');
}();//The parser can't understand
Copy Code

The calling method of defining a function should be print(); Then why it is enough to wrap the function body with ()?
It turns out that uses parentheses to define the function body, and the parser will call the defined function in the form of a function expression. In other words, any method that can turn a function into a function expression can make the parser call the defined function correctly. And ! is one of them, and + \- || ~ has such a function.

But please note that if you wrap the function body with parentheses, then execute it immediately. This method is only suitable for calling the function once, which involves a scope problem. When you want to reuse the function, the following problems will occur:

706fc8bd95f519079078693bc427c067.jpeg

image.png

But if you want to reuse the function, you can declare the function first, and then call the function. In the same parent scope, you can reuse the function, as follows:

var msg = function(msg) {}
msg();
Copy Code

This issue will be further analyzed later

function add ! before ?

Self-executing anonymous function:

In many js codes, we often see such a way of writing:

(function( window, undefined ) {
    //code
})(window);
Copy Code

We call this way of writing self-executing anonymous function. Just like its name, it executes itself. The first parenthesis is an anonymous function, and the latter parenthesis means immediate execution

As mentioned earlier, + \- || ~ these operators also have this function

(function () { /* code */ } ());
!function () { /* code */ } ();
~function () { /* code */ } ();
-function () { /* code */ } ();
 + function () { /* code */ } ();
Copy Code

1edd350d8ff794ab6e53dc21ab0ea3c6.jpeg

image.png

① ( ) has no practical meaning, does not operate the return value

② ! Negate the true and false of the return value

③ Bitwise inversion of the return value (the bitwise inversion of all positive integers is the negative number of itself + 1, the bitwise inversion of all negative integers is the absolute value of itself + 1, and the bitwise inversion of zero is -1. Among them, the bitwise inversion will also force the return value, converting the string 5 to the number 5, and then bitwise inversion. False is converted to 0, true is converted to 1. Other non-numbers Or the return value that cannot be converted into a digital type, it will be treated as 0 uniformly)

④ ~ +, – is to perform mathematical operations on the return value (it can be seen that when the return value is not a number type, +, – will perform forced conversion on the return value, and the string will be NaN after the forced conversion)

Let’s start with IIFE (Note: This example is for reference on the Internet)

IIFE (Immediately Invoked Function Expression)

function(){
    alert('IIFE');
}
Copy Code

Putting this code in console will result in an error

62b9481e097fcca638034380020c4682.jpeg

image.png

Because this is an anonymous function, in order to make it work properly, you must give a function name, and then call it through the function name.
In fact, after adding these symbols in front of the anonymous function, turns a function declaration statement into a function expression, and the expression will be automatically executed in the script tag .

So now after many codes are compressed and compiled, the exported js files are usually as follows:

(function(e,t){"use strict";function n(e){var t=e.length,n=st.type(e);return st.isWindow(e)?!1 :1===e.nodeType & amp; & amp;t?!0:"array"===n||"function"!==n & amp; & amp;(0=== t||"number"==typeof t & amp; & amp;t>0 & amp; & amp;t-1 in e)}function r(e){var t=Tt[e]={} ;return st.each(e.match(lt)||[],function(e,n){t[n]=!0}),t}function i(e,n,r,i){if( st.acceptData(e)){var o,a,s=st.expando,u="string"==typeof n,l=e.nodeType,c=l?st.cache:e,f=l ?e[s]:e[s] & amp; & amp;s;if(f & amp; & amp;c[f] & amp; & amp;(i||c[f].data)|| !u||r!==t)return f||(l?e[s]=f=K.pop()||st.guid + + :f=s),c[f]||(c [f]={},l||(c[f].toJSON=st.noop)),("object"==typeof n||"function"==typeof n) & amp; & amp;(i?c[f]=st.extend(c[f],n):c[f].data=st.extend(c[f].data,n)),o=c[f] ,i||(o.data||(o.data={}),o=o.data),r!==t & amp; & amp;(o[st.camelCase(n)]=r) ,u?(a=o[n],null==a & amp; & amp;(a=o[st.camelCase(n)])):a=o,a}}function o(e,t, n){if(st.acceptData(e)){var r,i,o,a=e.nodeType,u=a?st.cache:e,l=a?e[st.expando]:st.expando ;i f(u[l]){if(t & amp; & amp;(r=n?u[l]:u[l].data)){st.isArray(t)?t=t.concat(st .map(t,st.camelCase)):t in r?t=[t]:(t=st.camelCase(t),t=t in r?[t]:t.split(" ") );for(i=0,o=t.length;o>i;i ++ )delete r[t[i]];if(!(n?s:st.isEmptyObject)(r))return}( n||(delete u[l].data,s(u[l]))) & amp; & amp;(a?st.cleanData([e],!0):st.support.deleteExpando||u !=u.window?delete u[l]:u[l]=null)}}}function a(e,n,r){if(r===t & amp; & amp;1===e .nodeType){var i="data-" + n.replace(Nt,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"== typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null: + r + \ ""===r? + r:wt.test(r)?st.parseJSON(r):r}catch(o){}st.data(e,n,r)}else r=t}return r}function s(e){var t;for(t in e)if(("data"!==t||!st.isEmptyObject(e[t])) & amp; & amp;" toJSON"!==t)return!1;return!0}function u(){return!0}function l(){return!1}function c(e,t){do
Copy Code

Operator

Some people may wonder why operators can translate declarative functions into function expressions. This involves a concept parser

The program needs to be compiled or interpreted before running, and the source program is translated into bytecode, but before the translation, the program source code in the form of a string needs to be parsed into a data structure such as a syntax tree or an abstract syntax tree, which requires the use of to the parser

So what is a parser?

The so-called parser (Parser) generally refers to the process of converting text (string) in a certain format into a certain data structure. The most common parser (Parser) is to convert the program text into a data structure called an abstract syntax tree (AST) inside the compiler, which is also called a parser (Parser). There are also some simple parsers (Parser) for processing CSV, JSON, XML and other formats

When the JS parser performs the first step of pre-parsing, it will search from the beginning to the end of the code, and only look for content such as var, function, and parameters. The first step is generally called “JavaScript pre-parsing”. Moreover, when these contents are found, all variables are assigned a value in advance before the code is officially run: undefined; all functions are the entire function block before the code is officially run. For the parser to recognize that it is an expression, special symbols must be added to allow the parser to recognize it, such as the special operators just mentioned.

The parsing process is roughly as follows:

1. “Find something”: var, function, parameter; (also known as pre-parsing)

Remarks: If you encounter duplicate names, there are two situations: if you encounter variables and functions with duplicate names, only the function will be left; if you encounter functions with duplicate names, according to the context order of the code, keep the last one.

2. Interpret the code line by line.

Remarks: Expressions can modify the pre-parsed value (you can check the documentation yourself, this is what will be mentioned later)

Function declaration and function definition

Function declaration The generally relatively standardized declaration form is: fucntion msg(void) Note that there is a semicolon

function msg()
Copy Code

Function definition function msg()Note there is no semicolon

{
    alert('IIFE');
}
Copy Code

Function call

This is a function call

msg();
Copy Code

Add a () to the function declaration to call the function

function msg(){
    alert('IIFE');
}()
Copy Code

that’s all
But we executed it in console according to the above and found that something went wrong

86b7c2e0e61058a0d8b973ec0f2b0a17.jpeg

image.png

Because such code confuses function declaration and function call, the function `msg` declared in this way should be called as `msg()`.

If it is changed to (function msg())(), it will be such a structure: (function body) (IIFE), which can be recognized by the Javascript parser and executed normally

Learned from the pre-parsing process of the Js parser:

Parsers recognize a pattern: use parentheses to wrap functions. This is almost always a positive signal to the parser that the function needs to be executed immediately. If the parser sees an opening parenthesis followed by a function declaration, it will immediately parse the function. You can help the parser speed up parsing by explicitly declaring functions that execute immediately

That is to say, the function of parentheses is to declare a function, let the parser recognize it as an expression, and finally execute the function by the program

Summary

Any method that disambiguates between a function declaration and a function expression can be correctly recognized by the Javascript parser.

Assignment, logic, even commas, various operators, as long as the parser supports and recognizes special symbols can be used as a way to disambiguate, and !function() and (function()), is a way to convert it into an expression.

Test

As for which one to use first, () is recommended, and other operators, compared with one more execution step, such as + (expression), that is, immediately execute the + operator operation, roughly estimated one time:

174330667ff68aea090f122b29031d73.jpeg

image.png

Conclusion

From the screenshot of the test results, we can roughly see that the (IIFE) method is one level faster than the operator (speed of further digits), if the time complexity of immediate execution () is O(n) , then the operator is O(10n). Of course, this is only a rough test, and the parsing speed of existing browsers, the time base is so small that it can be ignored, so depending on personal needs, the way of writing is radish and cabbage. Everyone has their own well, it depends on the individual

About this article

Author: Tang Moxi

https://juejin.cn/post/7203734711780081722

Node Community



I have formed a Node.js community with a particularly good atmosphere, and there are many Node.js friends in it. If you are interested in learning Node.js (following plans are also possible), we can conduct Node.js-related activities together. Exchange, learn, build together. Just add a koala friend below and reply "Node".

   "Share, like, watch" a wave of support