0

在 zepto 的源代码中,我发现在 zepto.matches 函数中,有一个后备执行,

zepto.matches = 函数(元素,选择器){
    if (!element || element.nodeType !== 1) 返回 false
    var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector ||
                          element.oMatchesSelector || element.matchesSelector
    如果(matchesSelector)返回matchesSelector.call(元素,选择器)
    // 回退到执行选择器:
    var match, parent = element.parentNode, temp = !parent
    if (temp) (parent = tempParent).appendChild(element)
    匹配=〜zepto.qsa(父,选择器).indexOf(元素)
    temp && tempParent.removeChild(元素)
    返回匹配
  }

尽管使用了正常的 matchSelector 方式,但我对后备非常好奇,为什么要在前面添加~ :
~zepto.qsa(parent, selector).indexOf(element)

   document.getElementById("test");
   $.zepto.matches(a,"#test") // -1

它返回 -1 ,是对的还是我错过了什么?

4

1 回答 1

0

这是按位 NOT 运算符。在这种情况下,它用于有一个布尔返回值indexOfindexOf方法(数组,字符串),如果没有找到匹配则返回 -1,如果找到匹配则返回位置。当然,该位置也可以为 0。所以使用按位 NOT 运算符:

console.log(~-1); // 0
console.log(~0) // -1
console.log(~1) // -2
// and so on

所以因为在 JS0中被认为是一个“Falsy”值,而任何其他数字——除了NaN——是一个“Truthy”值,如果没有找到该元素,~zepto.qsa(parent, selector).indexOf(element)就会返回,因此线程可以在0代码:

var isFound = ~zepto.qsa(parent, selector).indexOf(element);

if (isFound) {
  // do something
}

但是,在这种情况下,我希望 zepto 方法返回一个真正的布尔值,因为它是一个 API 方法。在这种情况下,我宁愿简单地使用:

match = zepto.qsa(parent, selector).indexOf(element) > -1;

或者

match = !!~zepto.qsa(parent, selector).indexOf(element);

!它用于具有正确布尔表示的双精度:如果indexOf返回-1,则将其~转换为0,然后是第一个!in true,第二个是 in false,这是我们期望的“未找到”的布尔值。

Bitwise NOT 它也用于其他一些技巧,比如这个:

var words = ["a", "b", "c", "b", "b"];
var frequency = words.reduce(function(freq, word) {
    freq[word] = -~freq[word];
    return freq;
}, {})

此代码返回一个对象,如{a:1, b:3, c:1}; 它基本上计算数组中相同字符串值的频率。在这里,按位 NOT 它与一元否定运算符一起使用以具有增量计数器:所以如果freq[word]undefined- 因为这个词还没有在“字典”中 - 那么~undefinedis -1,并且一元否定变成了1。下次我们会有-~1,因此- -2,所以2;然后-~23等等。

位运算符非常有用,但也更容易被滥用。在某些情况下是必要的(例如,零填充右移它是目前 JS 中唯一可以替代 的方法ToUint32)它们不是,它们可能导致代码难以阅读。

但他们绝对值得为人所知。

于 2013-04-12T02:41:12.850 回答