Javascript 原型库的使用!!操作人员

Javascript 原型库的使用!!操作人员,javascript,Javascript,可能的重复项: 以下是Prototype Javascript库中的一个片段: Browser: (function(){ var ua = navigator.userAgent; var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; return { IE: !!window.attachEvent &&

可能的重复项:

以下是Prototype Javascript库中的一个片段:

  Browser: (function(){
    var ua = navigator.userAgent;
    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
    return {
      IE:             !!window.attachEvent && !isOpera,
      Opera:          isOpera,
      WebKit:         ua.indexOf('AppleWebKit/') > -1,
      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
      MobileSafari:   /Apple.*Mobile/.test(ua)
    }
  })(),
这一切都很好,我理解创建浏览器对象的目的。有一件事引起了我的注意,但我还没有弄清楚,那就是double not操作符的用法

如果你通读代码,你会在许多其他地方找到它。我不明白
之间有什么区别!!window.attachEvent
并仅使用
window.attachEvent


这只是一种约定,还是有更多不明显的约定?

这是一种相当常见的将值强制为布尔类型的技巧,而不是使用
(bool)
<代码>!window.attachEvent将否定
window.attachEvent
的真值,并给出一个布尔值<代码>!!window.attachEvent否定该值,为您提供原始真值,但作为布尔值,而不是
window.attachEvent

我不明白
之间有什么区别!!window.attachEvent
并仅使用
window.attachEvent

理解这一点的关键在于知道可以返回操作数,而不一定是布尔结果:

逻辑AND运算符(
&&
)将返回第二个操作数的值,如果第一个操作数为:

true && "foo"; // "foo"
如果第一个操作数本身为falsy,它将返回第一个操作数的值:

undefined && "anything"; // undefined
NaN && "anything";       // NaN
0 && "anything";         // 0
所以,在代码片段
!!window.attachEvent&!isOpera
,我们已经知道,
isOpera
是一个布尔值,
只需确保
Browser.IE
也是一个布尔结果


举个例子:假设我们在Firefox中,
窗口。attachEvent
未定义的
!isOpera
,如果不使用双重否定,
浏览器。IE
将为
未定义
而不是

@Daniel谢谢;我肯定这之前已经出现过,但正在搜索
是相当困难的+1,用于用示例进行出色的解释。太好了!在我看来,这是一个比公认的答案更好的答案(它更多地谈论了&&then!!)@Matt,真正的问题是“为什么要使用
!!window.attachEvent&&isOpera
”,而不仅仅是
window.attachEvent&&isOpera
”,OP并不是在问什么
确实如此(我认为OP已经知道这一事实)。了解您为什么需要
在这种情况下,您需要知道
&&
运算符的行为,这可能会导致混淆,因为在其他语言中,逻辑运算符总是生成布尔值。这就是为什么我要谈论
&&
;)@CMS我想他只是在问双重否定的意义是什么,他说:“如果你通读代码,你会在很多其他地方找到它。我不明白
!!window.attachEvent
和只使用
window.attachEvent
”有什么区别;他的例子使用了
&
,我认为这只是巧合。不过我觉得你的回答很有教育意义