Talking about Sizzle's "compiling principle" _ Other

Source: Internet
Author: User

Sizzle, a DOM selector engine written by jquery author John Resig, is the fastest-growing industry-first. As a standalone new selector engine, it appeared after the jquery 1.3 version and was taken as an Open-source project by John Resig. Sizzle is a separate part, not dependent on any library, if you do not want to use jquery, you can use only sizzle, can also be used for other frameworks such as: Mool, Dojo,yui and so on.

A few days ago, I was preparing a sharing ppt about jquery, asking my colleagues if there was anything else to know about jquery in addition to the way it was used, and someone mentioned trying to understand how its selector was implemented, and how the query speed of jquery was compared to other frameworks. On the speed, Sizzle's official website can download the test example, the speed does have the advantage. But why it has such a high rate of operation is related to the principle of implementation here.

Before you know about sizzle, you have to understand what the selector is, and here's a simple example, and the students who are familiar with jquery must be familiar with this selector format:

Copy Code code as follows:

Tag #id. class, A:first

It is basically from the left to the right layer of in-depth filtering to find matching DOM elements, this statement is not complicated. It is not difficult to assume that we are implementing this query ourselves. However, the query statement has only basic rules, no fixed number of selectors and order, how can we write code to adapt to this arbitrary arrangement? Sizzle can do all kinds of situations of normal analysis, implementation.

Sizzle's source code is indeed complex and not easy to understand its thinking. First put aside the outer layers of the package and look directly at what I personally think is the core of the entire implementation of the three methods:

The first core approach. Source Line 1052th has a tokenize function:

Copy Code code as follows:

function Tokenize (selector, parseonly) {}

The second argument, parseonly, means that only token serialization is done and no results are returned, in which case the serialized result is cached for backup. Selector is the query statement.

After this function is processed, such as selector= "#idtag. Class, A:first", you can get a format similar to the following result:

[
[
{matches: ' id ', type: ' ID '},
{matches: ' tag ', type: ' Tag '},
{matches: ' class ', type: ' class '},
...]
,
[
    {matches: "A", type: "TAG"}, ...],
[...
]


Seeing the name of the Tokenize function and its role, it makes it easy to associate the word "compiler". Here is a bit like lexical analysis, but this lexical analysis is simpler than the lexical analysis when compiling the program.

The Tokenize method will be based on the comma inside the selector, the regular expressions for spaces and relationship selectors do "participle" and get a two-dimensional array (allow me to take this not-so-accurate salutation), where the first-dimensional arrays are separated by commas and are called groups in the source code.

Let's look at the source code. Line No. 405 begins with the definition of expr = Sizzle.selectors = {}, where there is a definition of filter at line 567, where we can find the basic filter type: "ID", "TAG", "CLASS", "ATTR", " Child "," PSEUDO ", tokenize the type that is finally sorted out is also these kinds.

After "participle" is complete, still look at 405 lines defined expr= sizzle.selectors = {}. This will find all the selectors we are familiar with, and each selector corresponds to a method definition. Here should think of sizzle in fact is not through to selector do "participle", and then separately from expr inside to find the corresponding method to perform specific query or filter operation?

The answer is basically yes. But Sizzle has a more specific and ingenious approach. And the second way I think it's very central:

The source code 1293 line has a matcherfromtokens function:

Copy Code code as follows:

function Matcherfromtokens (tokens) {}

The incoming parameter is obtained from the Tokenize method. Matcher can be understood as the meaning of "matching programs", in which light literally acts as a function of generating matching programs through tokens. Indeed, indeed. Limited to space, this article for the moment only to share some of the sizzle I understand the principle of implementation, do not paste the source code. There is time behind me or a more detailed article on source analysis.

The Matcherfromtokens method confirms the previous assumption that it acts as a concatenation and link between the matching methods defined in selector "participle" and expr, and that the various permutations and combinations of selectors can be adapted. Sizzle Clever is that it does not directly to get the "participle" results and expr in a match-by-line execution, but first based on the rules of a large matching method, the last step to execute. But how to perform after the combination, but also to see the key third method:

The source code 1350 line has a Supermatcher method:

Copy Code code as follows:

Supermatcher = function (seed, context, XML, results, Expandcontext) {}

This method is not a directly defined method, but it is matcherfromgroupmatchers (Elementmatchers, setmatchers) method through 1345 lines, but it is important to perform the final function.

The Supermatcher method determines a starting query range based on the parameters seed, Expandcontext, and context, either directly from seed or from the parent node of the context. If you do not start with seed, it executes the code for expr.find["TAG" ("*", Expandcontext && Context.parentnode |) to wait for a Elems collection (array). Then do a traversal of the elems, match the elements inside using a Matcher method, and then heap the elements directly into the result set if the result is true.

All right, see here. The results of the original operation of the Matcher method are bool values, we return 405 rows to see the method contained in expr filter, is returned bool value. More pseudo class methods, including pseudo (pseudo classes), are the same. Seems to be a bit subversive to my original idea, it is not a layer of a layer down to check, but a bit back up to do matching, filtering meaning. In expr, only find and Prefilter return a collection.

Although here for a while with a bit of doubt, is the final why it uses a matching, filtering method to get the result set, but I think sizzle the most basic "compiler principle" should have been explained clearly.

But the doubt can't be kept, let's go on. In fact, this article itself has a little upside down to write the taste. Students who are interested in reading the source code will not see these three key methods from the beginning. In fact, Sizzle has done a series of other tasks before entering these three methods.

Sizzle's real entrance can be said to be in the 220 lines of the source code:

Copy Code code as follows:

function Sizzle (selector, context, results, seed) {}

This method is relatively easy to understand earlier, if you can match the selector is a single ID selector (#id), then directly based on the ID of the Context.getelementbyid (m) method to find out the elements. If you can match the selector is a single tag selector, you will first find the relevant elements directly using the Context.getelementsbytagname (selector) method. If the current browser is just a native getelementsbyclassname, and the matching to selector is a single class selector, the Context.getelementsbyclassname (m) method is also used to find the relevant elements. The three methods, which are browser-supported native methods, are certainly the highest performing efficiency.

If the most basic method is not used, it will enter the Select method. The source 1480 line has its definition:

Copy Code code as follows:

function Select (selector, context, results, seed, XML) {}

In the Select method, we will first do the "participle" operation we mentioned earlier for selector. But after this operation did not begin to assemble the matching method directly, but first did some find operation. The find operation here can correspond to the find in expr, which executes the query operation and returns the result set.

As you can see, select uses the word "participle" to find out the result set that can be looked up by the found method according to its type. When you do the find operation, you narrow the result set range from left to right in the order of the selectors. If a traversal is performed, all selectors in the selector can perform the find operation, and the result is returned directly. Otherwise, go to the "compile" procedure described earlier to perform the filtering process.

Here, also can shun come over, basically clear sizzle work flow. The question left in front of this time is not really a question, because the implementation of reverse matching filter, its search range has been filtered through the smallest set of layers. and the reverse matching filtering method for its corresponding to those selectors, such as pseudo-class, in fact, is also an efficient choice.

Let's briefly summarize why sizzle is very efficient.

first of all, from the processing process, it always first use the most efficient native methods to do the processing. The previous introduction is still only sizzle its own selector implementation method, the real sizzle execution, it will first determine whether the current browser support Queryselectorall native method (source code 1545 lines). If supported, then preference this method, browser native support method, the efficiency certainly than sizzle own JS write method to be high, the priority use also can guarantee sizzle higher work efficiency. (For more information on the Internet queryselectorall can be accessed). In the case that the Queryselectorall method is not supported, the sizzle is also a priority to solve the problem directly using getElementById, Getelementsbytag, Getelementsbyclassname and other methods.

second , the relatively complex situation, sizzle always choose to use the original method to query the selection to narrow the scope, and then use the "compiler principle" described earlier to treat the selection of elements one by one to match the filter. The workflow that goes into "compiling" is a bit more complex, and efficiency is certainly slightly lower than the previous approach, but sizzle is trying to minimize these methods while trying to give the result sets that are processed by these methods as small and simple as possible to achieve higher efficiency.

once again , even into this "compile" process, sizzle has done the caching mechanism that we have previously neglected and not introduced in order to prioritize and explain the process. The source code 1535 line is what we call a "compile" entry, which means that it invokes the third core method Supermatcher. To follow the 1466 line, the compile method caches the matching function generated by selector. More than that, and then to 1052 lines to see the Tokenize method, it will also be based on selector to do the word of the result of the cache. In other words, when we perform a sizzle (selector) method, the next time we call the sizzle (selector) method directly, its internal most performance of the "compile" process will not consume too much performance, direct access to the previous cache method. I was thinking that one of the biggest benefits of "compiling" might be that it was easy to cache, and the so-called "compile" might also be understood here as a function of generating preprocessing to store standby.

I hope that I can basically answer the questions of the students who care about the principle of implementation and efficiency of the selector. In addition, the analysis of the results from the sizzle the latest version of the source code, the article refers to the line number in this version of the source, you can download from the http://sizzlejs.com/. Time hasty, analysis there is not thoughtful place to make the bricks, please take mercy, there are questions of the students welcome offline continue to communicate.

The above mentioned is the entire content of this article, I hope you can enjoy.

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.