Analysis of prototype template class-template

Source: Internet
Author: User

Anyone who has used prototype knows that there is a class called template. The usage example is as follows:

VaR STR = '# {What} may have gone, but there is a time of # {how }';
VaR object = {
What: 'swallows ',
How: 'Return'
}
VaR template_1 = new template (STR );
VaR result = template_1.evaluate (object );

Console. Log ('result: ', result );
// Output: 'swallows may have gone, but there is a time of return'

This is quite convenient, so the following is a simple analysis of the implementation principle, which is also a note for source code interpretation.

Let's take a look at some of the situations that will be used in general requirements, or use the following example to determine our form. The replaced part is the content in the form of # {What, what is a keyword of an object.
Now, the question is, if the object is a nested object, how should we replace it?
That is:

<script type="text/javascript">
var object = {
what : {
name : 'Swallows'
},
how : 'return'
}
</script>

At the beginning, # {What} cannot meet the requirements. Therefore, we must specify # {What. name} Or # {What [name]} to replace nested objects.

The first example can be written:

<SCRIPT type = "text/JavaScript">
VaR STR = '# {What. name} may have gone, but there is a time of # {how }';
// Or str = '# {What [name]} may have gone, but there is a time of # {how }';
VaR object = {
What :{
Name: 'swallows'
},
How: 'Return'
}
VaR template_1 = new template (STR );
VaR result = template_1.evaluate (object );

Console. Log ('result: ', result );
// Output: 'swallows may have gone, but there is a time of return'
</SCRIPT>

The source code contains a regular var pattern =/^ ([^. [] + | \[((? :.*? [^ \])?) \]) (\. | \ [| $)/; Is used to achieve this purpose. And so on, any in-depth nesting can be implemented.

 

To replace, we need to have a replacement character method at the core. gsub is used in the source code. Below is a gsub Lite version:

<SCRIPT type = "text/JavaScript">
Function gsub (STR, pattern, replacement ){
VaR result = '',
Source = STR,
Match;
// Each of the following matches is divided into three parts.
// Equivalent to $ '$ & $'
While (source. length> 0 ){
Match = source. Match (pattern );
If (MATCH ){
Result + = source. Slice (0, match. Index );
Result + = replacement (MATCH );
Source = source. Slice (match. index + match [0]. Length );
} Else {
Result + = source;
Source = '';
}
}
Return result;
}
</SCRIPT>

The call method and principle are similar to the replace I mentioned earlier and can be exchanged. Http://www.cnblogs.com/xesam/archive/2011/12/05/2276783.html

<SCRIPT type = "text/JavaScript">
Console. Log (gsub ('there is a time of # {how} ',/(^ |. | \ r | \ n )(#\{(.*?) \})/, Function {
Return 'Demo ';
}))
// Output there is a time ofdemo
</SCRIPT>

 

The basic requirement is as follows: there are classes and methods.

<script type="text/javascript">
var Template = function(template, pattern){
this.template = template.toString();
this.pattern = pattern || Template.Pattern;
};
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype.evaluate = function(object){}
</script>

Template is the STR In the first example, pattern is the matching rule, and object is the object in the first example; the implementation of the evaluate method is now the focus:
Directly call the gsub method, mainly the replacement method in gsub.
Possible situations,
First, the object is an empty object, so we can directly delete the part to be replaced.
For example

var str = '#{what} may have gone, but there is a time of #{how}';
var object = {}

Then, 'may have gone, but there is a time of 'is returned directly'

Second, the escape part is retained directly.

var str = '\\#{what} may have gone, but there is a time of \\#{how}';
var object = {
what : 'Swallows',
how : 'return'
}

Then, the system directly returns '\\# {What} may have gone, but there is a time of \\#{ how }';

The specific code is as follows:

Template. Prototype. Evaluate = function (object ){
// Gsub (STR, pattern, replacement)
Return gsub (this. template, this. pattern, function (MATCH ){
VaR before = match [1]; // The Match [1] Here is the matching part of template. pattern (^ |. | \ r | \ n ).
VaR content = match [2]; // here match [1] is in template. pattern (#\{(.*?) \}) Matched parts
VaR expr = match [3]; // The Match [1] Here is (. *?) in template. pattern (.*?) Matching part
// Example:
// For s # {What}, before ='s ', content =' # {What} ', expr = 'wh'

// First, the object is an empty object, so we can directly delete the part to be replaced.
If (Object = NULL ){
Return (Match [1] + '');
}
// Second, the escape part is retained directly.
If (before = '\\'){
Return content;
}

// Except for the above two situations, the following is a normal replacement process.
VaR CTX = object;

// The following regular expression I mentioned earlier is used to match nested objects. Check the final (\. | \ [| $) to determine whether there is any nested child object matching.
// # '.' In {What. name '.'
// Or # {What [name '['
// Match [3]

VaR pattern =/^ ([^. [] + | \[((? :.*? [^ \])?) \]) (\. | \ [| $ )/;
Match = pattern.exe C (expr );

While (match! = NULL ){
If (/^ \ [/. Test (Match [1]) {
VaR comp = match [2]. Replace (// \\\]/g, ']');
} Else {
VaR comp = match [1];
}
CTX = CTX [comp]; // If CTX [comp] is a string, you can close the job in the following step. If CTX [comp] is still an object, Sorry, continue to work overtime.

If (null = CTX | ''= match [3]) {// If the nested sub-object of the object is not to be replaced, the loop is directly interrupted. Replaced successfully.
Break;
}

// The following is only to strip out the keywords, and other operations are used in the loop again.
If ('[' = match [3]) {
Expr = expr. substring (Match [1]. length)
} Else {
Expr = expr. substring (Match [0]. length)
}
Match = pattern.exe C (expr );
}

Return before + CTX;
});
};

 

Of course, the source code is not so simple. It also involves a write check and judgment, such as replacing the illegal characters of STR and processing the replacement as a string. For details, see the source code.
It may be complicated to handle the case where replacement is a string. gsub and template have a nested call, but the meaning is the same. Finally, you can lose a function.

For more information, see http://www.cnblogs.com/xesam /]
Address: http://www.cnblogs.com/xesam/archive/2011/12/05/2277260.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.