可能重复:
What does the exclamation mark do before the function?
我正在使用“推文”按钮维护现有网站,该按钮似乎来自this page
这里的一位同事提出了一个很好的问题:为什么这个脚本标记反转了这个自调用函数的(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-pro眼睛,似乎正在翻转undefined
的布尔值,从而允许整个<script>
标记评估为true。对于它的价值,这对我来说是一个完全陌生的想法(<script>
标签有一个表达式值。)
我的期望是,有一些特定的浏览器,其中<script>
标签的布尔值(是的,我甚至疯了,甚至打字)很重要。
所以基本的问题是这样的: <script>
对你知道的任何浏览器都有一个有意义的“表达式”值吗?和真实的含义是什么?在这种情况下与假?
答案 0 :(得分:4)
解释发生了什么以及为什么......
在Javascript中,您有function statements
和function expressions
。这两个是相似的,但不完全一样。
功能声明
function myTest() {return true;}
功能表达
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);
因评论而更新
//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)
我更喜欢第一个表单,因为它允许我在我的编辑器中使用块匹配工具,有时候有用的程序JSLint和JSHint首选f1
表单。
全部创建一个函数表达式,然后立即调用它。在 this 的情况下,Javascript编译器不需要parens,但它们对读者来说是一个非常有用的提示,这不是正常的赋值。
另一方面,你必须有某些东西告诉JS引擎你有一个函数表达式而不是函数语句。上面的=
符号有效,但是当没有作业时,您需要从某种运算符开始,无论是(+!
!function(x, y) {alert(x, y)}(1, 2);
前导运算符使其成为表达式。上面示例中的()
也强制它表达式。
答案 1 :(得分:0)
如果没有标识为twitter-wjs
的脚本元素,此代码会创建一个新脚本标记并将其添加到脚本类型的第一个元素之前。
由于!
是Javascript中的NOT运算符,因此当其操作数可以转换为true
时,它会计算为false
(在这种情况下,当没有标识为{{1}的元素时} exists,twitter-wjs
返回document.getElementById("twitter-wjs")
,这在Javascript中是一个假值,因此与undefined
运算符结合的结果将为!
,并且true
内的代码块{1}}被执行.Javascript中的任何对象在检查其布尔值时都是if
(尝试执行true
并且您将证明它),因此!![Object]
块不会在if
返回任何元素时执行。
更新:
关于你的评论,我看到@JeremyJStarcher的答案还可以,但我要补充一点:
在您的代码中,您有一个document.getElementById()
。对于function expression
,不需要标识符。但是在执行时,Javascript解释器可能会混淆并将其视为function expressions
。在function declaration
中,标识符不是可选的,因此解释器将抛出语法错误。为避免这种情况,此处使用function declarations
运算符,因此将其视为!
。