SoFunction
Updated on 2025-04-10

A brief analysis of the source code of Prototype String part (1) related to indexOf optimization

There are many ways to add it, but in summary, it is roughly divided into the following categories:

Classification Method name
Primitive capability enhancement strip |  include  |  startsWith  |  endsWith |  empty |  blank
Format camelize | capitalize |  underscore |  dasherize  | inspect          
Deformation toArray |  succ  | times
replace interpolate  | sub |  scan |  truncate | gsub
HTML processing stripTags  | escapeHTML |  unescapeHTML
Parameter serialization toQueryParams
JSON processing unfilterJSON |  isJSON |  evalJSON |  parseJSON
Script processing stripScripts |  extractScripts  | evalScripts

Starting from the basic primitive ability enhancement, the following is a specific implementation, which is easy to understand:

Copy the codeThe code is as follows:

(function(s){
function strip(){
return (/^\s+/,'').replace(/\s+$/,'');
}
function include(pattern){
return (pattern) > -1;//split
}
function startsWith(pattern) {
return (pattern, 0) === 0;
}
function endsWith(pattern) {
var d = - ;
return d >= 0 && (pattern, d) === d;
}
function empty() {
return this == '';
}
function blank() {
return /^\s*$/.test(this);
}
= || strip;
= include;
= startsWith;
= endsWith;
= empty;
= blank;
})();

The above strip is $.trim in jquery, and most of them seem to be trim. The tragedy of directly extending the native prototype here is revealed, because the later JS implementation (such as chrome) implements the trim method, which is backfiring.
Copy the codeThe code is as follows:

function strip(){
return (/^\s+/,'').replace(/\s+$/,'');
}

The replace(/^\s+/,'') here is trimLeft, and replace(/\s+$/,'') is trimRight, but there are no two methods.

Here are some interesting things in this part:

When I was watching this paragraph, I was very puzzled by the startsWith and endsWith. Logically speaking, it is enough to use indexOf to startsWith, but here I use lastIndexOf. Later, I looked at the implementation of Prototype version 1.6:
Copy the codeThe code is as follows:

function startsWith(pattern) {
return (pattern) === 0;
}

function endsWith(pattern) {
var d = - ;
return d >= 0 && (pattern) === d;
}

It can be seen that in the previous version, the startsWith used indexOf, but the 1.7 version modified the implementation of startsWith. In version 1.7:

In the startsWith implementation, lastIndexOf is searched from back to front, but the starting point (fromdex) is set to 0, so you only need to detect the beginning once.
In the endsWith implementation, indexOf is searched from front to back. Since the length of the string is uncertain, the length is calculated here, and then the starting point is determined. Therefore, it only needs to detect the end once.

The performance optimization here is that in the implementation of 1.6, if there is no match at the beginning (that is, startsWith is not true), indexOf will still look up backward until a match or end of a string is found, which is a waste. For example, for one of the following operations:

'abcdefgabcdefg'.startsWith('abc')
There is no difference in the implementation of version 1.6 and version 1.7, but let's convert it:

'abcdefgabcdefg'.startsWith('xesam')
In the 1.6 implementation, the indexOf operation inside startsWith will not match x after the beginning a does not match x. Although there is no need to continue, indexOf will continue to search backward until it finds the matching ‘xesam’ or end of the string.
In the 1.7 implementation, the lastIndexOf inside startsWith is in reverse search (fromIndex=0), so after the beginning a does not match x, the operation stops because lastIndexOf has already reached the end.
In this way, if the string to be detected is very long, the efficiency of the two implementation methods will be significantly different.
The principle of endsWith is the same.