Created
November 16, 2017 00:55
-
-
Save jarrodhroberson/ccbcac5d149a571edad9ca4d132b85e0 to your computer and use it in GitHub Desktop.
String.prototype.format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
String.prototype.format = function() { | |
var self = this, | |
formats = self.match(/{(:?\d*)}/g), // an array of formats `{}` found in the string | |
counter = 0, // A counter to keep track of what index to replace with | |
args = arguments; // Dereferencing arguments for use in the nested code blocks | |
if (formats) { | |
formats.forEach(function(format) { // We loop through each format expression in the array | |
var namedMatch = format.match(/{:(\d+)}/), // Checking if the format is a named replacement (i.e. {:1}) | |
reg; | |
if (namedMatch) { // If it is a named match, we replace all instances of that in one go. | |
reg = new RegExp(format, 'g'); | |
if (self.match(reg)) { // If the named match wasn't replaced yet, we replace it | |
self = self.replace(reg, args[namedMatch[1]]); // Make the replacement | |
/** | |
* The counter is used to make sure we're always replacing in the right order. | |
* String.format() will replace all non-named replacements `{}` with | |
* the first unused string replacement in args. | |
* | |
* Example: | |
* ``` | |
* "Hello {}! My name is {:1}. I love {}, because I am {:1}. I also like {}. See you later -{:1}" | |
* .format('world', 'Kyle', 'candy', 'jazz'); | |
* ``` | |
* | |
* Flow: | |
* (counter = 0) | |
* First {} -> 'world' ( counter = 1 ) | |
* All {:1} -> 'Kyle' ( counter = 2 ) | |
* Second {} -> 'candy' ( counter = 3 ) | |
* Second {:1} -> not replaced ( counter = 3 ) | |
* Final {} -> 'jazz' ( counter = 4 ) | |
* ------------------------------------------- | |
* Output: "Hello world! My name is Kyle. I love candy, because I am Kyle. I also like jazz. See you later -Kyle" | |
* | |
* As you can see, we maintained the order of replacements for non-named values, | |
* while still replacing with named values | |
*/ | |
counter+= counter > namedMatch[1] ? 0 : 1; | |
} | |
} else { | |
reg = new RegExp(format); // If it's not a named replacement... | |
self = self.replace(reg, args[counter]); // replace it with the next replacement in line | |
counter+= 1; | |
} | |
}); | |
} | |
return self; // return the completed string (this) | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment