Sizzle engine-Impact of native getelementsbyclassname on selection results (jquery)

Source: Internet
Author: User

I personally think this example may not be of practical significance, but it can be a good understanding of the sizzle selection process.

Instance description

Let's take a look at an example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<body>
<p class="tab" id="a1">1</p>
<p class="tab" id="a2">2</p>
<p class="tab" id="a3">3</p>
<script type="text/javascript" src="../sizzle.js"></script>
<script type="text/javascript">
console.log(Sizzle('.tab:not(:first)'));
console.log(Sizzle('p:not(:first)'));
console.log(Sizzle('p.tab:not(:first)'));
</script>
</body>

Looking at the three expressions of the above three results, it is estimated that many people will think that the results must be the same. Good, except IE6/7/8, the results should be the same. Result (1 ):

    console.log(Sizzle('.tab:not(:first)'));  //[#a2,#a3]
console.log(Sizzle('p:not(:first)')); //[#a2,#a3]
console.log(Sizzle('p.tab:not(:first)')); //[#a2,#a3]

But in IE6/7/8, the result is (2 ):

    console.log(Sizzle('.tab:not(:first)'));  //[#a1,#a2,#a3]
console.log(Sizzle('p:not(:first)')); //[#a2,#a3]
console.log(Sizzle('p.tab:not(:first)')); //[#a2,#a3]

In fact, it is not only IE6/7/8, but any browser result that does not support the getelementsbyclassname method is result (2.

Result Analysis

In result (1,

'. Tab: Not (: First:
1. Document. getelementsbyclassname ('. Tab') to obtain the result set [# A1, # A2, # A3];
2. filter: Not (: First) to obtain the result set [# A2, # A3];
'P: Not (: First:
1. Document. getelementsbytagname ('P') to obtain the result set [# A1, # A2, # A3];
2. filter: Not (: First) to obtain the result set [# A2, # A3];
'P. Tab: Not (: First:
1. Document. getelementsbyclassname ('. Tab') to obtain the result set [# A1, # A2, # A3];
2. Filter P to obtain the result set [# A1, # A2, # A3];
3. filter: Not (: First) to obtain the result set [# A2, # A3];

In result (2:

'. Tab: Not (: First:
1. Document. getelementsbytagname ('*') to obtain the result set [HTML, head, body, # A1, # A2, # A3, script, script]
2. filter: Not (: First) to obtain the result set [head, body, # A1, # A2, # A3, script, script].
3. Filter. tab to obtain the result set [# A1, # A2, # A3]
'P: Not (: First:
1. Document. getelementsbytagname ('P') to obtain the result set [# A1, # A2, # A3];
2. filter: Not (: First) to obtain the result set [# A2, # A3];
'P. Tab: Not (: First:
1. Document. getelementsbytagname ('P') to obtain the result set [# A1, # A2, # A3];
2. filter: Not (: First) to obtain the result set [# A2, # A3];
3. Filter. tab to obtain the result set [# A2, # A3]

We can see that the process is the same in the two cases without the class. When there is a class, we will first find the elements containing the class, this directly affects the candidate sets of the subsequent filtering steps.

Cause Analysis

As for the cause, let's go back to the code level to explain:

The first influencing factor is:

First look at the sizzle. Find Section

for ( i = 0, len = Expr.order.length; i < len; i++ ) {}

Expr.order: [ "ID", "NAME", "TAG" ];

In the initial search, the matching type has a priority id --> name --> tag. For browsers that support getelementsbyclassname, the sizzle source code is processed as follows:

In row 3:

Expr.order.splice(1, 0, "CLASS");
Expr.find.CLASS = function( match, context, isXML ) {
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
return context.getElementsByClassName(match[1]);
}
};

Therefore, in a browser that supports getelementsbyclassname, the implementation of sizzle. Find becomes

for ( i = 0, len = Expr.order.length; i < len; i++ ) {}

Expr.order: [ "ID","CLASS" "NAME", "TAG" ];

In addition, the class priority is second only to ID.

Therefore, in the first step of filtering, the candidate sets of different browsers are different.

 

The second factor is:

Let's look at the sizzle. filter section.

for ( type in Expr.filter ) {}
Expr.filter={
CLASS: function( match, curLoop, inplace, result, not, isXML ) {},
ID: function( match ) {},
TAG: function( match, curLoop ) {},
CHILD: function( match ) {},
ATTR: function( match, curLoop, inplace, result, not, isXML ) {},
PSEUDO: function( match, curLoop, inplace, result, not ) {}
POS: function( match ) {}
},

A significant difference between this and sizzle. Find is the for. In loop used here. There is no definite sequence [Priority], so it is not guaranteed what type to filter first.

So. Tab: Not (: First) First filters: Not (: First), and then filters. tab, so the results are inconsistent with what you think.

Third influencing factor:

This involves the implementation of filter. For expressions containing not, the candidate set will be filtered again.

. Tab: Not (: First) Changes in the not part of the set and removes the first element directly.

. Tab: First is not changed because first is processed in POS matching.

 

Solution

If we change the implementation of sizzle. Filter to be consistent with that of sizzle. Find, it will become the following form:

for ( i = 0, len = Expr.filterOrder.length; i < len; i++ ) {}

Expr.filterOrder: [ "ID","CLASS" "NAME", "TAG" ,"ATTR","CHILD","PSEUDO","POS"];

Then we can ensure that the selected results are consistent with the expected ones. However, it is obviously not suitable for such a case.

Another method is to avoid using this ambiguous selector. Instead of Directly Writing: Not (: First) as a method call to the set.

In addition, if you know the DOM structure, there are many processing methods, such as adding tag restrictions and hierarchical restrictions.

Description

This problem does not occur in the absence of a similar selection expression. You can view the filter section of the sizzle source code.

The filter part is annoying and has no time to write the filter part recently. If you have any mistakes, please contact us.

For more information, see http://www.cnblogs.com/xesam /]
Address: http://www.cnblogs.com/xesam/archive/2012/02/21/2361591.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.