Enumerating and thinking of JavaScript splicing HTML string

Source: Internet
Author: User

Reprint over, remove some nonsense bar.

Goal:

Convenient splicing string, do not use the dizzying + =. Use the following procedure:

1, first create a string as "template", such as: ' My name is ${name},i\ ' m ${age}. '

2, pass an object in, which contains the value you want to fill in the template, such as: {name: ' LIX ', age:11}

3, finally you can get the string you want, such as: My name is Lix,i ' M 11.

Call Method:

Mix (' My name is ' ${name} ', I\ ' m ' ${age} ', ' {name: ' LIX ', age:11})

Or

Mix (' My name is ' ${0} ', I\ ' m ' ${1} '. ', [' LIX ', 11])

Several implementations:

1,replace+regexp

Seen in Masaki's article. Here's the simplified code:

1 function Mix (str,group) {2         str = str.replace (/\$\{([^{}]+) \}/gm,function  (m,n) {  3             return (group[n]! = undefined)? Group[n]: "; 4         })5         return  str; 6     }

One of the m,n inside the function is worth talking about. Where did they pass the value? is the regular expression. The Replace method of string, if the 2nd argument is a function, then the 1th parameter value of the function is definitely "the string that is currently matched."

But here the function has two parameters, the 2nd parameter n, what is it? He's the 1th group in your regular group (the part that's wrapped up in the 1th group)--that is, if you want to, you can have many groups, and the Replace function can have a number of parameters.

Replace accepts a handler function whose first argument is the substring that is currently matched, followed by a regular match to the 1th group, the 2nd group ...

The return in the function is the top priority, and if there is no return, then the substitution does not occur. Replace is replacing the substring that was previously matched with the return string (that is, the parameter m).

The principle of this method is easy to understand, the code is also small, but there is a problem, I found this test is more than using the normal + = series String 10 times times slower than!! Oh, that's so chilling.

I am very covet to this handy and useful way of spelling strings, so I can only consider how to improve their efficiency.

Method Two

Since the replace+ regular expression is inefficient, I'm going to try to do without the Replace method. The Lookup field label (that is, ${name}) is still done with the regular, and after it is found, we intercept the string before the tag, and then the part after it-just remove the ${name} This section, and then with the + directly connected to the value of this tag (in the example is Lix), so loop.

The code is as follows:

 1  function   LoopMix0 (str,group) { 2  var  reg =/\$\{([^{}]+) \}/GM, Res;  3  while  (res = Reg.exec (str)) { 4  str = STR.SUBSTR (0,res.index) + ((Group[res[1]] ! = undefined)? GROUP[RES[1]]: +str.substr (Res.index+res[0].length);  5   6
      return   str;  7 } 

The regular Exec method is a rather peculiar method, because he does not return all substrings that match the matching criteria at once, but returns only the current match at a time . 1 sub-strings , the detailed format is this:

[The substring currently matched to, (if there is a regular grouping, then this is the value grouped by grouping, Group 1, Group 2 ...), index (this is the index of the substring currently matched to)]

If you're going to be able to match all the matches by exec, it's just a loop. After each match, exec changes his own lastindex property so that the next time exec does not match the previous match again. When exec does not return a result, it means that the match is complete.

So there is no replace, but the use of the original method of the string, the efficiency should be improved it?

The reality is brutal, and the efficiency of this method and Method 1 has barely improved. The disadvantage of this method is obvious, just like replace, every time the loop is still the entire string to do the operation (constantly give new values, and then with the new value into the next cycle), of course, the efficiency can not be improved.

Method Three

Understand the shortcomings of Method 2, to make improvements is very simple. I create a new empty string, and then still press the loop above, but each time the field label in the first part, the field label corresponding to the value, the next part of the field label to connect to the empty string. This way, although the empty string is getting longer, we never have to modify the original string every time-the original string is the longest.

The code is as follows:

1 functionloopMix1 (str,group) {2         varreg =/\$\{([^{}]+) \}/gm, res,returnstring = ", start = 0;3          while(res =reg.exec (str)) {4Returnstring + = str.substring (Start,res.index) + ((group[res[1]]! = undefined)? Group[res[1]]: ');5Start = Res.index+res[0].length;6         }7Returnstring + =str.substr (start);8         returnreturnstring;9}

It is important to have a variable start that holds the starting position of the next str start intercept.

PS: At the end of the loop, add the last section of the original string to the returnstring, otherwise you will not be "as long as you expect".

There is a change in this code that is no longer a substr, but a substring. Because the 2nd parameter of substr is length, it is no longer suitable here.

This method is more than 1 time times faster than Method 2!

Speaking of substr and substring, you have to mention a "glamorous" (confusing mystery): substr and substring of the 2nd parameter of each what meaning? How can we not confuse?

It's really simple:substr is much shorter than substring, so it desperately needs "length", so his 2nd parameter is length.

Method Four

Method 3 is good, but I am a man of excellence. Method 3 In theory there is a disadvantage, is that the original string Str has not changed, each time the cycle is the same length, will not drag the regular and substring efficiency?

So I'm going to have to shorten the Str every time, anyway, the former half is also no longer the same. The code is as follows:

1 functionloopMix2 (str,group) {2         varreg =/\$\{([^{}]+) \}/gm, res,returnstring = ", start = 0;3          while(res =reg.exec (str)) {            4Returnstring + = str.substring (0,res.index) + ((group[res[1]]! = undefined)? Group[res[1]]: ');5Start = Res.index+res[0].length;6str =str.substr (start);7Reg.lastindex = 0;8         }9Returnstring + =str;Ten         returnreturnstring; One}

The code does not just shorten the STR, but also resets the REG query subscript, in case.

Is this a step further than the last method? The answer is no, this method is slower than Method 3, due to excessive operation in the loop, resulting in no increase in efficiency. But it's faster than the method.

Method Five

Since our field label ${name} is relatively easy to identify, we can use the native method of string to extract the field label, and then splice it, without intentionally mistaking Str.

The idea is to find the ' ${', then follow the obtained index, find the Next '} ', and then take the middle value, you get the key value of the field label, and then get the corresponding value from the group, and then spell the result string. The code is as follows:

1 functionloopMix3 (str,group) {2         varindex=0,close=0,returnstring = ", name =";3          while(index = str.indexof (' ${', index))!==-1) {   4Returnstring + =str.substring (close,index);5Close = Str.indexof ('} ', index);6Name = Str.substring (index+2, close);7Returnstring + = (Group[name]! = undefined)? Group[name]: "8index =Close;9Close +=1;Ten         } OneReturnstring + =str.substr (close); A         returnreturnstring; -}

Important : It is particularly important to change the starting position (index) of the indexOf lookup at any time, as well as where the substring starts to intercept (close).

This method is completely useless regular, but the efficiency is not improved, completely compared to Method 3, is also the cycle of too much operation?

PS: The code for this method has a bug, such as the string as follows: ' My name is ' ${name} ', the is a half ${name. { $name} ', which is what I mean by "deliberately" mistake the string, but this bug is also very good fix, as long as the find a ${, after the find}, continue to find ${, if there is a result, continue the next cycle. But as a result, one more judgment, the efficiency is even worse.

Method Six

Often write this code, suddenly think of another way of thinking. For example, this method.

String has a own method split that splits the string into an array by a delimiter, and split supports regular expressions! That is to say, I can put my original string as a ${name} to the group of the field label!

And then, although the string is folded, but we do not get all the field label AH? String has a match method that returns a substring of all matching parameters, and he also accepts the regular and returns the array!

So I'm taking this right now. Two operations, one is to break the original string as a delimiter, and the second is to use it to extract all the field tags in the original string.

Now that we have two arrays, if we put the two arrays together from beginning to finish, we can get the original string! Of course, we can't spell it as it is ...

Now we're going to loop the array and stitch it up. Let's ask you two questions before this:

1. The same string split and match the same regular operation, the returned array which is long?

2. What is the array returned by ' ${name}${name}${name}${name}${name}${name}${name}${name '. Split (' ${name} ')?

It is important to ask these two questions, which are inseparable from the implementation of this function.

It is easy to find that match returns an array that is always 1 less than the array length returned by split! So, with the aim of holding the loop as short as possible, we're going to loop through the array of match returns instead of split.

The code is as follows:

functionMatchmix (str, group) {varReg =/\$\{[^{}]+\}/GM; varStrarr =Str.split (REG); varLabelarr =Str.match (REG); varreturnstring = ' ', I= 0, label, Len=labelarr.length;  for(; i < Len; i++) {Label= Labelarr[i].slice (2,-1); Returnstring+ = Strarr[i] + (Group[label]! =NULL? Group[label]: "); }      returnReturnstring +Strarr[i]; }

PS: Note that the last item of the split array is also added to the result string after the loop is finished! Remember!

This method is slightly faster than Method 3, but the gap is small. I suspect that this method should be dominant in the case of long strings.

Beyond the idea of optimization

With the original method Mix (replace+regexp), his efficiency is there any way to improve it? The answer is YES!

Above all the ideas, you can see that I use the same regexp, namely/\$\{([^{}]+) \}/gm, he is divided into groups. And the match we need here is very simple, in fact, can not group! Because we just need to get ${name}, we can easily get the name: Cut it off with slice !

So the changed mix is as follows:

1 //Original2 functionMix (str,group) {3         returnStr.replace (/\$\{([^{}]+) \}/GM,function(m,n) {4             return(Group[n]! =void1)? Group[n]: ";5         })6     }7 //Version Slice8     functionmix1 (str,group) {9         returnStr.replace (/\$\{[^{}]+\}/GM,function(m,n) {Tenn = M.slice (2,-1); One             return(Group[n]! =void1)? Group[n]: "; A         }) -}

Compared with the two, the efficiency is high or low? Tested, MIX1 is slightly more efficient in all browsers

As a result, the efficiency of regular expressions has yet to be improved.

Here are some related tests:

Mix and mix1 contrast

This improved method is also suitable for other ideas.

Summarize

In addition to the off-the-shelf method 1, the following method can be said that I now want to come out, but the results are not satisfactory, and not as I would like to be more efficient situation, can only say exercise a bit of thinking it.

If this result is not a blow, then I will tell you a "exciting" news:IE9, the most efficient is method 1, that is, the original Replace+regexp method ! All the following methods are white blind, haha!

However, the fastest replace method under IE9 does not perform as many times as the slowest replace method under Chrome.

Speaking of which, I would like to say: I was tested with jsperf.com. Test address

Jsperf not only can be compared, and each test has a number of executions, IE9 under replace although the most efficient, but the number of executions is still not up to chrome under replace the number of executions.

There are already 6 versions of the test address, because I tested and suddenly came up with new ideas, and jsperf Riga new test code will be new version. Where version 6 is the most complete method.

After repeated testing in various browsers, I found:

1,chrome efficiency is the fastest, but the test results are not! Often! No! Stability! Availability Often this run and next run is exactly two results
2,firefox is less efficient than chrome, but stable, and test results are consistent with Chrome's conclusions
3,IE9 efficiency is the worst! The conclusion is also very wonderful!

Other tests

3 Most efficient methods, method one, method three, method six competition

Original: http://jo2.org/javascript-join-html-string/

Enumerating and thinking of JavaScript splicing HTML string

Related Article

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.