4

可能重复:
函数前的感叹号有什么作用?

我正在维护一个带有“tweet”按钮的现有网站,该按钮似乎来自此页面

这里的一位同事提出了一个很好的问题:为什么这个脚本标签会反转undefined这个自调用函数的(通过无返回语句)值?(为了阅读方便,原文在链接中)

<script>
  !function(d,s,id) {
//^--- that
    var js,fjs=d.getElementsByTagName(s)[0];
    if(!d.getElementById(id)) {
      js=d.createElement(s);
      js.id=id;
      js.src="https://platform.twitter.com/widgets.js";
      fjs.parentNode.insertBefore(js,fjs);
    }
  }(document,"script","twitter-wjs");
</script>

在我的非 JS 专业人士看来,这似乎是在翻转 的布尔值undefined,从而允许整个<script>标签评估为真。对于它的价值,这对我来说是一个完全陌生的想法(该<script>标签具有表达式值)。

我的期望是有一些特定的浏览器,<script>标签的布尔值(是的,即使打字我也觉得很疯狂)很重要。

所以基本的问题是:对于你知道的任何浏览器,a是否<script>具有有意义的“表达式”值?在这种情况下,真与假的隐含含义是什么

4

2 回答 2

4

An explanation of what is going on and why...

In Javascript, you have function statements and function expressions. The two of them are similar, but not exact.

Function statement

function myTest() {return true;}

Function Expressions

var f = function() {return true;}
alert(f()); //

alert(function() { return true}); // Return value is used

// and even

(function(x, y) {
  var z, x; // private variables, hidden from the outside scope
  var r = x  + y;
  // Return value is ignored.
}(1, 2));

// The ! can be used to start a function expression too.
// This is totally legal Javascript, but it isn't in the normal
// "vernacular" of the langage
!function(x, y) {
  var z, z1; // Private vars
  // Do something with side effects
  // Return value is ignored.
}(x, y);

Updated due to comments

//The following code works identical:
var v1 = (function(a, b) {return a+b}(1,2));
var v2 = (function(a, b) {return a+b})(1,2);
var v3 = function(a, b) {return a+b}(1,2)

I prefer the first form because it lets me use the block matching tools on my editor, and the f1 form is preferred by the sometimes useful programs JSLint and JSHint.

All create a function expression and then invoke it immediately. In this case, the parens are not needed by the Javascript compiler, but they serve as a very useful hint to the reader that this is not a normal assignment.

On the other hand, you must have something to tell the JS engine that you have a function expression instead of a function statement. The = sign above works, but when there is no assignment, you need to start off with some kind of operator, be it (+!

!function(x, y) {alert(x, y)}(1, 2);

The leading operator makes it an expression. The () in the above examples force it to an expression as well.

于 2012-10-24T17:20:10.837 回答
0

如果没有带有 id 的 script 元素,此代码将创建一个新的 script 标签并将其添加到 script 类型的第一个元素之前twitter-wjs

由于!是 Javascript 中的 NOT 运算符,因此它计算其操作数何时true可以转换为(在这种情况下,当不存在false具有 id 的元素时返回内部的代码块被执行。Javascript中的任何对象都会在检查其布尔值时(尝试做,你会证明它),所以当任何元素返回时,该块将不会被执行。twitter-wjsdocument.getElementById("twitter-wjs")undefined!trueiftrue!![Object]ifdocument.getElementById()

更新:
关于您的评论,我看到@JeremyJStarcher 的回答还可以,但我要添加一些内容:
在您的代码中,您有一个function expression. 不需要function expressions标识符。但是在执行时,Javascript 解释器可能会混淆并认为它是一个function declaration. 在function declarations中,标识符不是可选的,因此解释器会抛出语法错误。为了避免这种情况,!这里使用了运算符,因此它将被视为function expression.

于 2012-10-24T17:05:02.417 回答