JavaScript中如何转义引号

253

我正在从数据库输出值(它不是公开的输入,但用户在公司可以进行输入 - 这意味着,我不担心XSS)。

我正在尝试输出这样的标签:

<a href="" onclick="DoEdit('DESCRIPTION');">Click Me</a>

DESCRIPTION其实是来自数据库的一个值,类似于这样:

Prelim Assess "Mini" Report

我尝试用 \ 替换 ",但无论我尝试什么,Firefox都会在单词 Assess 后的空格处截断我的 JavaScript 调用,这导致了各种问题。
我一定是错过了显而易见的答案,但是我无论如何都想不出来。
有人能指出我的愚蠢吗?
以下是整个 HTML 页面(最终将成为 ASP.NET 页面,但为了解决此问题,我除了问题代码之外删除了其他所有内容)。
<html>
    <body>
        <a href="#" onclick="DoEdit('Preliminary Assessment \"Mini\"'); return false;">edit</a>
    </body>
</html>

3
onclick事件的绑定方式改为不显眼的,并将所有数据库信息移入数据岛中是一个好主意。这样可以使代码更加清晰,当字符串转义出错时,还能获得某种语法错误提示。 - Justin Johnson
1
可能是重复的问题,参考 *如何在onClick处理程序内部的JavaScript代码中转义字符串?*。 - Peter Mortensen
你也可以使用 escape("string") 和 unescape("string") jQuery 方法。 - Abhiram
13个回答

242

您需要转义写入到 DoEdit 中的字符串以清除双引号字符。他们导致 onclick HTML 属性过早关闭。

在 HTML 上下文中使用 JavaScript 转义字符 \ 是不足够的。您需要将双引号替换为正确的 XML 实体表示,即 &quot;


1
对,但这不是这个吗? <a href="#" onclick="DoEdit('Preliminary Assessment "Mini"'); return false;">编辑</a> 我试过了,还是出错了。这一定是个简单的 WTF,但却找不到原因。 - Matt Dawdy
4
这不是 JavaScript 的问题,而是 HTML/XML 编码的问题:在属性值中不能使用双引号字符而不进行转义处理,否则浏览器/解析器会认为你已经结束了属性值声明。 - Aaron
30
请将文本从英语翻译成中文。仅返回已翻译的文本:示例替换代码:“'mystring'.replace(/"/g, '"');” - Joshua Burns
3
在之前的评论中多了一个引号。可行的代码是'mystring'.replace(/'/g, '"');。 - Agustin Lopez
我知道这是一个老问题,但为什么不简单地使用encodeURIComponent() / decodeURIComponent() - 据我所知,它们完全可以满足您的需求,并且自阿姆斯特朗登月以来或者差不多那个时候就一直存在,即所有浏览器都支持它。 - Adergaard
显示剩余4条评论

114
"&quot;在这种特定情况下可以使用,正如我之前建议的那样,因为这是HTML上下文。

然而,如果您希望JavaScript代码独立于任何上下文进行转义,您可以选择使用本地JavaScript编码:
'变成\x27
"变成\x22

因此,您的onclick将变成:
DoEdit('初步评估\x22Mini\x22');

例如,将JavaScript字符串作为参数传递给另一个JavaScript方法时,也可以使用此方法(alert()是此类测试方法)。

我参考了重复的Stack Overflow问题,如何转义onClick处理程序内的JavaScript代码中的字符串?


2
谢谢!你的答案更正确,因为它是原生JavaScript,不受上下文影响。 - scarver2
2
这是正确的答案,尽管在HTML上下文中使用&quot;当然也可以。 - Oliver
请注意,在输入值中需要使用&quot;,例如 <input value="\x22quoted string\x22"> 将无法正常工作。 - thdoan
@10basetom 自然地,JavaScript 转义只在 JavaScript 上下文中起作用,比如事件处理程序 (onclick="...")。value 属性的值不会在 JavaScript 上下文中被处理,只会在 HTML 上下文中被处理。 - tsemer
1
替换代码:'mystring'.replace(/"/g, '\\x22').replace(/'/g, '\\x27') - chickens

34
<html>
    <body>
        <a href="#" onclick="DoEdit('Preliminary Assessment &quot;Mini&quot;'); return false;">edit</a>
    </body>
</html>

应该能起作用。


28

各位,JavaScript中已经有unescape函数用于对\"进行反转义:

<script type="text/javascript">
    var str="this is \"good\"";
    document.write(unescape(str))
</script>

3
“escape”和“unescape”的组合实现了我所需的功能。谢谢。 - Luis R.
11
"escape/unescape已被弃用,虽然encodeURI不仅仅是引用。 http://gotochriswest.com/blog/2011/05/23/escape-unescape-deprecated/" - chug2k

14

基本上,这是我做的方式:str.replace(/[\""]/g, '\\"')

var display = document.getElementById('output');
var str = 'class="whatever-foo__input" id="node-key"';
display.innerHTML = str.replace(/[\""]/g, '\\"');

//will return class=\"whatever-foo__input\" id=\"node-key\"
<span id="output"></span>


13

问题在于HTML不认可转义字符。你可以通过在HTML属性中使用单引号,在onclick中使用双引号来解决这个问题。

<a href="#" onclick='DoEdit("Preliminary Assessment \"Mini\""); return false;'>edit</a>

5
哎呀,我在想为什么过去我自然而然地使用'来表示属性。其实我从未深入研究过它。谢谢。 - Matt Dawdy

2

如果你正在Java中组装HTML,你可以使用Apache commons-lang中的这个实用工具类,来正确地执行所有转义操作:

org.apache.commons.lang.StringEscapeUtils
可以为Java、JavaScript、HTML、XML和SQL转义和反转义字符串。


我在Java中使用org.apache.commons.lang3.StringEscapeUtils.escapeEcmaScript(text)来构建methodExpression。谢谢。 - Harun

2
请查看以下代码,它使用正则表达式作为一部分来转义输入字符串中的单引号。它验证用户输入的字符串是否以逗号分隔,并且同时转义输入字符串中的任何单引号。
为了转义单引号,只需在字符串中输入反斜杠后跟一个单引号,例如:\'。我在此示例中使用了jQuery验证器,您可以根据自己的方便使用。
有效的字符串示例:
'Hello'
'Hello', 'World'
'Hello','World'
'Hello','World',' '
'It\'s my world', 'Can\'t enjoy this without me.', 'Welcome, Guest' HTML:
<tr>
    <td>
        <label class="control-label">
            String Field:
        </label>
        <div class="inner-addon right-addon">
            <input type="text" id="stringField"
                   name="stringField"
                   class="form-control"
                   autocomplete="off"
                   data-rule-required="true"
                   data-msg-required="Cannot be blank."
                   data-rule-commaSeparatedText="true"
                   data-msg-commaSeparatedText="Invalid comma separated value(s).">
        </div>
    </td>

JavaScript:

     /**
 *
 * @param {type} param1
 * @param {type} param2
 * @param {type} param3
 */
jQuery.validator.addMethod('commaSeparatedText', function(value, element) {

    if (value.length === 0) {
        return true;
    }
    var expression = new RegExp("^((')([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.\\-_\\[\\]\\)\\(]+([^\'\\\\]*(?:\\\\.[^\'\\\\])*)('))(((,)|(,\\s))(')([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.\\-_\\[\\]\\)\\(]+([^\'\\\\]*(?:\\\\.[^\'\\\\])*)('))*$");
    return expression.test(value);
}, 'Invalid comma separated string values.');

1
你可以复制下面列出的这两个函数,用它们来转义/取消转义所有引号和特殊字符。你不需要使用 jQuery 或任何其他库来完成此操作。
function escape(s) {
    return ('' + s)
        .replace(/\\/g, '\\\\')
        .replace(/\t/g, '\\t')
        .replace(/\n/g, '\\n')
        .replace(/\u00A0/g, '\\u00A0')
        .replace(/&/g, '\\x26')
        .replace(/'/g, '\\x27')
        .replace(/"/g, '\\x22')
        .replace(/</g, '\\x3C')
        .replace(/>/g, '\\x3E');
}

function unescape(s) {
    s = ('' + s)
       .replace(/\\x3E/g, '>')
       .replace(/\\x3C/g, '<')
       .replace(/\\x22/g, '"')
       .replace(/\\x27/g, "'")
       .replace(/\\x26/g, '&')
       .replace(/\\u00A0/g, '\u00A0')
       .replace(/\\n/g, '\n')
       .replace(/\\t/g, '\t');

    return s.replace(/\\\\/g, '\\');
}

对我来说不起作用。它无法转义双引号。 - CanCoder

1

我已经使用jQuery做了一个示例

var descr = 'test"inside"outside';
$(function(){
   $("#div1").append('<a href="#" onclick="DoEdit(descr);">Click Me</a>');       
});

function DoEdit(desc)
{
    alert ( desc );
}

这在Internet Explorer和Firefox中都可以工作。


5
当然会影响,因为你没有直接放在属性里。要使用你的方法,我必须创建一个JS字符串数组,然后进行任意数量的 $("#divxxx")... 赋值操作。这不是最优解,但还是谢谢你的建议。 - Matt Dawdy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接