Javascript 感叹号在函数之前做什么?
它返回语句的计算结果是否为false。例如:Javascript 感叹号在函数之前做什么?,javascript,function,Javascript,Function,它返回语句的计算结果是否为false。例如: !function () {}(); 可以使用它两次将值强制为布尔值: !false // true !true // false !isValid() // is not valid 因此,要更直接地回答您的问题: !!1 // true !!0 // false 编辑:它的副作用是将函数声明更改为函数表达式。例如,以下代码无效,因为它被解释为缺少所需标识符(或函数名称)的函数声明: 职能: functio
!function () {}();
可以使用它两次将值强制为布尔值:
!false // true
!true // false
!isValid() // is not valid
因此,要更直接地回答您的问题:
!!1 // true
!!0 // false
编辑:它的副作用是将函数声明更改为函数表达式。例如,以下代码无效,因为它被解释为缺少所需标识符(或函数名称)的函数声明:
职能:
function () { return false; }(); // syntax error
不返回任何内容(或未定义)
有时,我们希望在创建函数时正确调用它。您可能会尝试以下方法:
function () {}
但它会导致一个语法错误
使用函数将其视为表达式之前的code>运算符,因此我们可以调用它:
function () {}()
这也将返回与函数返回值相反的布尔值,在本例中为true
,因为!未定义的
为真
。如果希望实际返回值是调用的结果,请尝试以下方法:
!function () {}()
JavaScript语法101。下面是一个函数声明:
(function () {})()
请注意,没有分号:这只是一个函数声明。您需要一个调用,foo()
,才能实际运行该函数
(function(){})();
现在,当我们添加看似无害的感叹号时:!函数foo(){}
将其转换为表达式。它现在是一个函数表达式
!function bool() { return false; }() // true
!function bool() { return true; }() // false
当然,代码>本身并不能调用函数,但我们现在可以将()
放在末尾:!函数foo(){}()
,其优先级高于
并立即调用该函数
(function(){})();
因此,作者所做的是为每个函数表达式保存一个字节;更具可读性的书写方式是:
function foo() {}
最后,
使表达式返回true。这是因为默认情况下,所有立即调用的函数表达式(IIFE)都返回未定义的,,这给我们留下了!未定义
,即为真
。不是特别有用。感叹号使任何函数始终返回布尔值。
最后一个值是函数返回值的求反
(function(){})();
省略上述示例中的代码>将是一个语法错误
!function bool() { return false; }() // true
!function bool() { return true; }() // false
然而,实现这一目标的更好方法是:
function bool() { return true; }() // SyntaxError
使用有一个很好的理由上标记的函数调用的代码>
一般来说,在单独的文件(aka模块)上使用这种技术是一个好主意,这些文件后来被连接起来。这里需要注意的是,文件应该由将新文件放在新行的工具连接起来(这对于大多数concat工具来说都是常见的行为)。在这种情况下,请使用
将有助于避免前面连接的模块遗漏尾随分号时出现错误,但这将提供将它们按任意顺序排列的灵活性,而无需担心
(function bool() { return true; })() // true
工作原理与
!function abc(){}();
!function bca(){}();
但保存一个字符和任意的外观更好
顺便说一句,+
,-
,~
,void
操作符中的任何一个在调用函数方面都具有相同的效果,可以肯定的是,如果您必须使用某个东西从该函数返回,它们的行为会有所不同
!function abc(){}();
(function bca(){})();
但如果您使用IIFE模式进行一个文件一个模块的代码分离,并使用concat工具进行优化(这使得一行一个文件工作),那么构建
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?
将执行安全的代码,与第一个代码示例相同
这一个将抛出错误,因为JavaScript ASI将无法完成其工作
!function abc(/*no returns*/) {}()
+function bca() {/*no returns*/}()
关于一元运算符的一个注意事项是,它们将执行类似的工作,但仅在第一个模块中未使用的情况下。因此,如果您不能完全控制连接顺序,它们就不那么安全
这项工作:
!function abc(/*no returns*/) {}()
(function bca() {/*no returns*/})()
这不是:
!function abc(/*no returns*/) {}()
^function bca() {/*no returns*/}()
是一个逻辑NOT运算符,它是一个布尔运算符,将某个对象反转为其相反的对象
尽管您可以通过在函数前面使用BANG(!)来绕过被调用函数的括号,但它仍然会反转返回值,这可能不是您想要的。与IEFE的情况一样,它将返回undefined,当反转为布尔值true时,它将返回undefined
如果需要,请使用右括号和砰(!)
其他工作人员
组合运算符
它是编写IIFE(立即调用的函数表达式)的另一种方式
它的另一种写作方式-
+!(function(){ return false; }());
=> 1
-!(function(){ return false; }());
=> -1
!+(function(){ return false; }());
=> true
!-(function(){ return false; }());
=> true
~!(function(){ return false; }());
=> -2
~!!(function(){ return false; }());
=> -1
+~(function(){ return false; }());
+> -1
同
(function( args ) {})()
当我们进行javascript缩小时,只需保存一个字节的数据。
考虑下面的匿名函数
!function ( args ) {}();
为了使上面的代码成为自调用函数,我们通常会将上面的代码更改为
function (){}
现在,除了在函数末尾添加调用函数所需的()
之外,我们还添加了两个额外字符(,)
。在缩小的过程中,我们通常注重减小文件大小。所以我们也可以把上面的函数写成
(function (){}())
尽管如此,这两个函数都是自调用函数,我们还保存了一个字节。我们只使用了一个字符,而不是两个字符(,)
代码>这是唯一能解释问题的答案,太棒了!您的第二个代码示例不是有效的JavaScript。的目的
是将函数声明转换为函数表达式,仅此而已。@Andrey引导程序twitter在所有javascript(jQuery)插件文件中都使用了它。添加此注释以防其他人也有相同的问题。d3.js也使用!功能
syntax@Andrey-我在最小化代码中看到了这一点,其中保存一个额外字节是一个胜利。+1这是唯一的答案,它实际上解决了为什么要这样做,以及为什么人们看到它使用m
(function (){}())
!function (){}()