What does the exclamation mark do before the funct

2018-12-30 23:54发布

!function () {}();

10条回答
妖精总统
2楼-- · 2018-12-31 00:34

JavaScript syntax 101. Here is a function declaration:

function foo() {}

Note that there's no semicolon: this is just a function declaration. You would need an invocation, foo(), to actually run the function.

Now, when we add the seemingly innocuous exclamation mark: !function foo() {} it turns it into an expression. It is now a function expression.

The ! alone doesn't invoke the function, of course, but we can now put () at the end: !function foo() {}() which has higher precedence than ! and instantly calls the function.

So what the author is doing is saving a byte per function expression; a more readable way of writing it would be this:

(function(){})();

Lastly, ! makes the expression return true. This is because by default all IIFE return undefined, which leaves us with !undefined which is true. Not particularly useful.

查看更多
大哥的爱人
3楼-- · 2018-12-31 00:41

There is good point for using ! for function invocation marked on airbnb JavaScript guide

Generally idea for using this technique on separate files (aka modules) which later get concatenated. Caveat here is that files supposed to be concatenated by tools which put new file at new line (which is anyway common behavior for most of concat tools). In that case using ! will help to avoid error in if previously concatenated module missed trailing semicolon, and yet that will give flexibility to put them in any order with no worry.

!function abc(){}()
!function bca(){}();

Will work same as

!function abc(){}()
;(function bca(){})();

but saves two characters and arbitrary looks better.

And by the way any of +,-,~,void operators have same effect, in terms of invoking function, for sure if you have use something to return from that function they would act differently.

abcval = !function abc(){return true;}() // abcval equals false
bcaval = +function bca(){return true;}() // bcaval equals 1
zyxval = -function zyx(){return true;}() // zyxval equals -1
xyzval = ~function xyz(){return true;}() // your guess?

but if you using IIFE patterns for one file one module code separation and using concat tool for optimization (which makes one line one file job), than construction

!function abc(/*no returns*/) {}()
+function bca() {/*no returns*/}()

Will do safe code execution, same as a very first code sample.

This one will throw error cause JavaScript ASI will not be able to do its work.

!function abc(/*no returns*/) {}()
(function bca() {/*no returns*/})()

One note regarding unary operators, they would do similar work, but only in case they used not in the first module. So they are not so safe if you do not have total control over the concatenation order.

This works:

!function abc(/*no returns*/) {}()
^function bca() {/*no returns*/}()

This not:

^function abc(/*no returns*/) {}()
!function bca() {/*no returns*/}()
查看更多
步步皆殇っ
4楼-- · 2018-12-31 00:43

Let's save a few other bytes!

(() => {})()

example:

(() => {return "yeah"})()
查看更多
旧人旧事旧时光
5楼-- · 2018-12-31 00:46

And here's something more I figured out from the console. As mentioned earlier, the exclamation mark makes the function return a boolean.

For the latter one of the syntax:

( function my_function() {} )()

We can do something like:

(function add_them(a,b) { return a+b;} )(9,4)

Like a simultaneous function definition and call.

Edit:
Now you would ask what's the use of '!' type function definition. Let's consider the following:

!function a_would_be_function() { alert("Do some junk but inside a function"); }()

you would want to execute a function like above, but without a '!' would generate an error. Hope I'm clear.

查看更多
浅入江南
6楼-- · 2018-12-31 00:47

Its another way of writing IIFE (immediately-invoked function expression).

Its other way of writing -

(function( args ) {})()

same as

!function ( args ) {}();
查看更多
只若初见
7楼-- · 2018-12-31 00:49

It returns whether the statement can evaluate to false. eg:

!false      // true
!true       // false
!isValid()  // is not valid

You can use it twice to coerce a value to boolean:

!!1    // true
!!0    // false

So, to more directly answer your question:

var myVar = !function(){ return false; }();  // myVar contains true

Edit: It has the side effect of changing the function declaration to a function expression. E.g. the following code is not valid because it is interpreted as a function declaration that is missing the required identifier (or function name):

function () { return false; }();  // syntax error
查看更多
登录 后发表回答