87

Is there an easy equivalent to this in JavaScript?

$find = array("<", ">", "\n"); $replace = array("&lt;", "&gt;", "<br/>"); $textarea = str_replace($find, $replace, $textarea); 

This is using PHP's str_replace, which allows you to use an array of words to look for and replace. Can I do something like this using JavaScript / jQuery?

... var textarea = $(this).val(); // string replace here $("#output").html(textarea); ... 
3
  • 3
    Just for clarification, are you doing this to escape html? Commented Feb 21, 2011 at 18:11
  • Multiple replace instead of single replace? If you want to do anything like that efficiently, you need a regular expression. That is not what the selected answer is doing. Commented May 4, 2018 at 19:55
  • See this post, I think it is what you are looking for Commented Jul 17, 2018 at 22:37

19 Answers 19

94

You could extend the String object with your own function that does what you need (useful if there's ever missing functionality):

String.prototype.replaceArray = function(find, replace) { var replaceString = this; for (var i = 0; i < find.length; i++) { replaceString = replaceString.replace(find[i], replace[i]); } return replaceString; }; 

For global replace you could use regex:

String.prototype.replaceArray = function(find, replace) { var replaceString = this; var regex; for (var i = 0; i < find.length; i++) { regex = new RegExp(find[i], "g"); replaceString = replaceString.replace(regex, replace[i]); } return replaceString; }; 

To use the function it'd be similar to your PHP example:

var textarea = $(this).val(); var find = ["<", ">", "\n"]; var replace = ["&lt;", "&gt;", "<br/>"]; textarea = textarea.replaceArray(find, replace); 
Sign up to request clarification or add additional context in comments.

13 Comments

Thanks bob, assuming this is using prototype(?) would you know how to do this using jQuery?
@Tim This is regular JavaScript, no extra library needed. JavaScript is a prototypal language which means every object has a prototype it inherits from. Adding to the object's prototype is simply a way to extend all such objects.
"tar pit".replaceArray(['tar', 'pit'], ['capitol', 'house']) // "cahouseol house"
This solution doesn't work for the following: String: "The cat hits the dog" find array: ['cat', 'dog'] replace array: ['dog, 'cat']
@derekdreery The function neither work for strings that contains RegExp characters, for example: find array ["(", ")"] replace array ["[", "]"]
|
59

Common Mistake

Nearly all answers on this page use cumulative replacement and thus suffer the same flaw where replacement strings are themselves subject to replacement. Here are a couple examples where this pattern fails (h/t @KurokiKaze @derekdreery):

function replaceCumulative(str, find, replace) { for (var i = 0; i < find.length; i++) str = str.replace(new RegExp(find[i],"g"), replace[i]); return str; }; // Fails in some cases: console.log( replaceCumulative( "tar pit", ['tar','pit'], ['capitol','house'] ) ); console.log( replaceCumulative( "you & me", ['you','me'], ['me','you'] ) );

Solution

function replaceBulk( str, findArray, replaceArray ){ var i, regex = [], map = {}; for( i=0; i<findArray.length; i++ ){ regex.push( findArray[i].replace(/([-[\]{}()*+?.\\^$|#,])/g,'\\$1') ); map[findArray[i]] = replaceArray[i]; } regex = regex.join('|'); str = str.replace( new RegExp( regex, 'g' ), function(matched){ return map[matched]; }); return str; } // Test: console.log( replaceBulk( "tar pit", ['tar','pit'], ['capitol','house'] ) ); console.log( replaceBulk( "you & me", ['you','me'], ['me','you'] ) );

Note:

This is a more compatible variation of @elchininet's solution, which uses map() and Array.indexOf() and thus won't work in IE8 and older.

@elchininet's implementation holds truer to PHP's str_replace(), because it also allows strings as find/replace parameters, and will use the first find array match if there are duplicates (my version will use the last). I didn't accept strings in this implementation because that case is already handled by JS's built-in String.replace().

7 Comments

@StephenM.Harris Cool answer, you have noticed too that almost all answers in the page are using cumulative replacements.
This doesn't work when replacing characters like brackets. For example, it's common to use ((placeholder)) style tags and this will replace it those ((undefined)) jsfiddle.net/oLfmeaa6/1
@MacroMan fixed! Had to update the regex that escapes special regex chars (which just sounds bug-prone :D). Thanks for pointing this out!
Love this code. Addendum: I changed it to replaceBulk(str, obj) {var findArray = Object.keys(obj), var replaceArray = Object.values(obj);....} So, I can pass in a simple hash-object of {"x":"y"...} replacements. Seems easier to maintain.
@HoldOffHunger The double array inputs are truer to PHP's str_replace() this was intended to emulate -- but that aside I prefer the object input too! Just keep in mind Object.values will not work in IE without a polyfill.
|
24
text = text.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br/>'); 

2 Comments

This is not "at once". Basically the same as this "one-liner": text = text.replace(foo); text = text.replace(bar);
@Beejor To be fair, the accepted answer is not "at once" either, it just hides the subsequent replacements behind a function.
13

A more visual approach:

String.prototype.htmlProtect = function() { var replace_map; replace_map = { '\n': '<br />', '<': '&lt;', '>': '&gt;' }; return this.replace(/[<>\n]/g, function(match) { // be sure to add every char in the pattern return replace_map[match]; }); }; 

and this is how you call it:

var myString = "<b>tell me a story, \n<i>bro'</i>"; var myNewString = myString.htmlProtect(); // &lt;b&gt;tell me a story, <br />&lt;i&gt;bro'&lt;/i&gt; 

1 Comment

Error: this.replace is not a function !
12

You could use the replace method of the String object with a function in the second parameter to avoid replacing a string that was previously replaced:

First Method (using a find and replace Object)

var findreplace = {"<" : "&lt;", ">" : "&gt;", "\n" : "<br/>"}; textarea = textarea.replace(new RegExp("(" + Object.keys(findreplace).map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|") + ")", "g"), function(s){ return findreplace[s]}); 

jsfiddle

Second method (using two arrays, find and replace)

var find = ["<", ">", "\n"]; var replace = ["&lt;", "&gt;", "<br/>"]; textarea = textarea.replace(new RegExp("(" + find.map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|") + ")", "g"), function(s){ return replace[find.indexOf(s)]}); 

jsfiddle

Desired function:

function str_replace($f, $r, $s){ return $s.replace(new RegExp("(" + $f.map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|") + ")", "g"), function(s){ return $r[$f.indexOf(s)]}); } $textarea = str_replace($find, $replace, $textarea); 

EDIT

This function admits a String or an Array as parameters:

function str_replace($f, $r, $s){ return $s.replace(new RegExp("(" + (typeof($f) === "string" ? $f.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&") : $f.map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|")) + ")", "g"), typeof($r) === "string" ? $r : typeof($f) === "string" ? $r[0] : function(i){ return $r[$f.indexOf(i)]}); } 

7 Comments

looks cool, but not work in some cases :( . e.g. {'[0-1]':'NUM'}
Hi @Soyoes, tell me in what cases it fails and I'll try to fix it.
Hi @Soyoes, I've tested it and it works: [jsfiddle] (jsfiddle.net/uxv2u9n0)
Hi , I tried something like this {'My':'Your', '[0-1]':'NUM'} with str "My name is Peter, Am 19", using the 1st method.
This method is to search and replace Strings or Array of Strings. It not works with RegExps, if you want to use a RegExp like a search parameter, you need to parse the find Array to convert it into RegExp. I'll give you an example in a couple of minutes.
|
7

A simple forEach loop solves this quite well:

let text = 'the red apple and the green ball'; const toStrip = ['red', 'green']; toStrip.forEach(x => { text = text.replace(x, ''); }); console.log(text); // logs -> the apple and the ball 

Comments

6

The top answer is equivalent to doing:

let text = find.reduce((acc, item, i) => { const regex = new RegExp(item, "g"); return acc.replace(regex, replace[i]); }, textarea); 

Given this:

var textarea = $(this).val(); var find = ["<", ">", "\n"]; var replace = ["&lt;", "&gt;", "<br/>"]; 

In this case, no imperative programming is going on.

Comments

5

Using ES6: There are many ways to search for strings and replace in JavaScript. One of them is as follow

const findFor = ['<', '>', '\n']; const replaceWith = ['&lt;', '&gt;', '<br/>']; const originalString = '<strong>Hello World</strong> \n Let\'s code'; let modifiedString = originalString; findFor.forEach( (tag, i) => modifiedString = modifiedString.replace(new RegExp(tag, "g"), replaceWith[i]) ) console.log('Original String: ', originalString); console.log('Modified String: ', modifiedString);

1 Comment

I used this method and it is elegant and works. Unfortunately, YUI compressor 2.4.8 cannot handle the ES6 and crashes.
4

You might want to look into a JS library called phpJS.

It allows you to use the str_replace function similarly to how you would use it in PHP. There are also plenty more php functions "ported" over to JavaScript.

http://phpjs.org/functions/str_replace:527

Comments

4
String.prototype.replaceArray = function (find, replace) { var replaceString = this; for (var i = 0; i < find.length; i++) { // global replacement var pos = replaceString.indexOf(find[i]); while (pos > -1) { replaceString = replaceString.replace(find[i], replace[i]); pos = replaceString.indexOf(find[i]); } } return replaceString; }; var textT = "Hello world,,,,, hello people....."; var find = [".",","]; var replace = ['2', '5']; textT = textT.replaceArray(find, replace); // result: Hello world55555 hello people22222 

1 Comment

This prototype does not work if you enter these vars: var find = [".",","]; var replace = [',', '.'];
4

const items = { '<': '&lt;', '>': '&gt;', '\n': '<br/>', } const re = new RegExp('[' + Object.keys(items).join('') + ']', 'g') const input = '<foo>\n<bar>' const output = input.replaceAll(re, key => items[key]) console.log(output)

Comments

2

There is no way to do this in one method call, you'll have to either chain calls together, or write a function that manually does what you need.

var s = "<>\n"; s = s.replace("<", "&lt;"); s = s.replace(">", "&gt;"); s = s.replace("\n", "<br/>"); 

1 Comment

I like it simple. Was looking for a similar function from php. OK, copy-past - but 3 lines - no a whole prototype function.
2

For the tags, you should be able to just set the content with .text() instead of .html().

Example: http://jsfiddle.net/Phf4u/1/

var textarea = $('textarea').val().replace(/<br\s?\/?>/, '\n'); $("#output").text(textarea); 

...or if you just wanted to remove the <br> elements, you could get rid of the .replace(), and temporarily make them DOM elements.

Example: http://jsfiddle.net/Phf4u/2/

var textarea = $('textarea').val(); textarea = $('<div>').html(textarea).find('br').remove().end().html(); $("#output").text(textarea); 

Comments

0

A version with an object as a parameter:

String.prototype.strtr = function (replace) { keys = Object.keys(replace); result = this; for (i = 0; i < keys.length; i++) { result = result.replace(keys[i], replace[keys[i]]); } return result; } function htmlspecialchars(str) { return String(str).strtr({">": "&gt;", "<": "&lt;", "\n": "<br/>"}); } // usage text = "<span>spam</span>"; htmlspecialchars(text); 

Comments

0

jquery have a solution for that.

var htmlString = $( element).html(); $( element ).text( htmlString );

view here: https://api.jquery.com/html/

Comments

0

wrap all this in a function, you can pass both an array and a string

function str_replace(search,replace,subject) { if(!Array.isArray(search)){ subject = subject.replace(new RegExp(search, "g"), replace) } else{ search.forEach( (tag, i) => subject = subject.replace(new RegExp(tag, "g"), replace[i]) ) } return subject; } 

Comments

0

Just that!

let v = "Test's <<foo>> ((baAr))"; console.log(v); const r = ['<', '>', 'a', '\\)', '\\(', '\'' ]; for (var i = r.length - 1; i >= 0; i--) { v = v.replace((new RegExp(r[i], "gi")), "_"); } console.log(v);

1 Comment

More escapes: const r = ['<', '>', '\)', '\(', '\'', ',', '\\.', ';', '`', '"', '#', '/', '\\\\', '=', '\\+', '\*', '%', '\\$', '\\?', '!', '&', '{', '}', '\[', '\]', '~', '\\^', '\\|', ':'];
0

If you're looking for something quick and easy, try this:

let sr = {'<': '&lt;', '>': '&gt;', '\n': '<br/>'}; let text = '<p>This text \n spans \n multiple\nrows.</p>'; function str_replace(obj, str) { Object.entries(obj).forEach((e) => str = str.replaceAll(e[0], e[1])); return str; } // and run it console.log(str_replace(sr, text));

Disclaimer: This function uses cumulative replacement and an object for search/replace (evidently)

Comments

-1

One method would be:

var text = $(this).val(); text = text.replace(/</g, "&lt;").replace(/>/g, "&gt;"); $("#output").html(text); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.