Identifying text Signatures
Let's take a look at the overload use cases mentioned in the previous article:
Copy Code code as follows:
var extend = overload
. Add ("*, ...",
function (target) {})
. Add ("Boolean, *, ...",
function (deep, target) {});
We allow the user to enter a string representing the signature of an overload. When the user calls the function, we need to take the user input parameter instance to compare with each parameter type on the signature, so we need to convert the string to an array of types first. In other words, the string "Boolean, number, array" should be converted to an array [Boolean, number, array].
Before making the conversion, we first consider dealing with two special types, representing any type of "*" and representing any number of "...". We can define two proprietary types for them to make special compatibility handling within Overload:
Copy Code code as follows:
Overload.any = function () {};
Overload.more = function () {};
After these two types, the string "boolean, *, ..." is correctly converted to an array [Boolean, Overload.any, Overload.more]. Since both Overload.any and overload.more are functions, nature can also be regarded as a type.
Once these two types are properly processed, we can begin writing a transformation function that recognizes the text signature:
Copy Code code as follows:
if (Signature.replace (/^\s+|\s+$)/ig, "") = = "") {
Signature = [];
} else {
Signature = Signature.split (",");
for (var i = 0; i < signature.length; i++) {
var typeexpression = signature[i].replace (/(^\s+|\s+$)/ig, "");
var type = null;
if (typeexpression = = "*") {
Type = Overload.any;
else if (typeexpression = = "...") {
Type = Overload.more;
} else {
Type = eval ("+ typeexpression +"));
}
Signature[i] = type;
}
}
I think this code is fairly easy to understand, so it's no longer explained. The first time I wrote this code, I forgot to write the first if, so that the blank signature string "" could not be properly identified as an array of blank signatures [], but luckily my unit test code discovered the flaw at the first moment. It seems that writing the unit test code is still very important.
matching function Signature
After we get the type array of the function signature, we can use it to match the instance array of the input parameter to find the correct overload. Before we discuss how to match the signature of a function, let's look at how a language like C # or vb.net handles function overload matching. The common language process for function overload matching is this:
Number of arguments-overload with incorrect number of arguments will be excluded
Parameter type-The argument type cannot be implicitly converted to a signature type is excluded
Number of matches-after elimination, the number of matching signatures remains the same with different processing methods
0 matches-no hits matched
1 matches-This is a hit match.
2 or more matches-if you can find a best match in these matches, hit the best match;
In this section, we first deal with the first two steps in the process, removing the signatures of the number of parameters or inconsistent parameter types:
Copy Code code as follows:
var matchsignature = function (Argumentsarray, signature) {
if (Argumentsarray.length < signature.length) {
return false;
else if (Argumentsarray.length > Signature.length &&!signature.more) {
return false;
}
for (var i = 0; i < signature.length; i++) {
if (!) ( Signature[i] = = Overload.any
|| Argumentsarray[i] instanceof Signature[i]
|| Argumentsarray[i].constructor = = Signature[i]) {
return false;
}
}
return true;
};
For length comparisons, we need to give special treatment to "..." that represents any number of arguments outside of this function:
Copy Code code as follows:
if (signature[signature.length-1] = = Overload.more) {
Signature.length = signature.length-1;
Signature.more = true;
}
This piece of code will be consolidated into the end of the first section of the transformation function so that the Matchsignature function can easily determine whether the parameter matches the signature. Ideally, we would match the input parameter type to 0 or 1 overloads, so it's easy to tell which overload to hit. But if there are 2 or more overloads that match, then we're going to pick an optimal one, which is what the next section discusses.
handling multiple matches
About C # is how to choose a more matching overload from multiple matches, you can see the relevant chapters in C # Language specification. I think there are three simple examples to illustrate the problem:
Copy Code code as follows:
Long Sum (int x, int y) {return x + y;}
Long Sum (long x, long y) {return x + y;}
Sum (0, 1);
Because the 0 and 1 parameters are interpreted by the compiler as type int, they do not have to be cast for the 1th overload, and they all have a type conversion to the 2nd overload, so the 1th overload is superior.
Copy Code code as follows:
Long Sum (int x, long y) {return x + y;}
Long Sum (long x, int y) {return x + y;}
Sum (0, 1);
On the 1th parameter, the 1th overload is superior, and the 2nd overload is superior on the 2nd parameter. In this case, none of the overloads are superior to the other, and an error is not found for the superior overloaded compiler.
Copy Code code as follows:
Long Sum (int x, int y) {return x + y;}
Long Sum (int x, long y) {return x + y;}
Long Sum (long x, int y) {return x + y;}
Sum (0, 1);
On the 1th parameter, the 1th overload is better than the 3rd overload, and the 2nd overload is the same; on the 2nd parameter, the 1th overload is superior to the 2nd overload, which is the same as the 3rd overload. Although the 2nd overload is not good for the 3rd overload, we can determine that the 1th overload is better than them, so the compiler chooses the 1th overload.
Suppose we have a overloadcomparator comparison function that compares the pros and cons of any two signatures, do we need to compare the signatures by just 22 to find the optimal overload? In fact, it is not necessary, we can use the array of the sort method, let it call overloadcomparator to sort, and then verify the relationship between the first two can be-if the tie, then do not hit any one, if there are successively, then hit the first one.
The specific overloadcomparator code is not given here, it relies on another comparison function named Inheritancecomparator to compare the parameter types of the two signatures to which one has the actual incoming parameter type. There is a clever way to determine whether two types are inherited and who inherits from them.
Summary
Now we have a JavaScript function overload library, complete code see here: function Overload library overload. Hopefully this library will help you improve the readability of JavaScript code and reduce the maintenance costs of large AJAX projects.