Ideally, you want each match to start exactly where the previous match ended. Otherwise, it is too easy to get out of sync with escape sequences. @outis regex is close, but it cannot escape the second single quote in '\\' . After the first match, it must match at least one reverse callback and one single quote, which it cannot do. If there are more characters, it skips ahead and begins to match after the second single quote.
Try instead:
result = subject.replace(/([^'\\]*(?:\\.[^'\\]*)*)'/g, "$1\\'");
This is an example of a Friedl "expanded cycle" template:
normal * (special normal *) *
[^'\\]* is the "normal *" part; it absorbs any number of characters except single quotes or backslashes. If the next character is a backslash, \\. ("special") consumes this, and the next character (backslash, single quote, or something else) and [^'\\]* captures again. Repeat as necessary.
The key point is that the regular expression never skips forward, and it never returns. If he sees a backslash, he always consumes this and the next character, so he never goes out of sync.
source share