为什么在字符串中使用JavaScript转义引号的字符需要是\\'而不是\'?

5
我在ASP.NET的代码后端中使用JavaScript时遇到了问题,经过几个小时的研究,发现问题是转义字符引起的。
一开始我使用了这个。
ScriptManager.RegisterStartupScript(this, this.GetType(), "temp", "alert('Can't delete this data because it is bound with rate plan');", true);

这会产生JavaScript错误,因为“can't”中的引号需要使用转义字符,所以我使用了。
ScriptManager.RegisterStartupScript(this, this.GetType(), "temp", "alert('Can\'t delete this data because it is bound with rate plan');", true);

但它仍然不起作用。
最后我使用了。
ScriptManager.RegisterStartupScript(this, this.GetType(), "temp", "alert('Can\\'t delete this data because it is bound with rate plan');", true);

“而且这很好。 我只是好奇为什么我们需要使用\\'而不是\'才能使转义字符正常工作。”
5个回答

7

\ 是C#和JavaScript中的转义字符。

当你在C#中输入 "\'" 时,它会创建一个包含撇号的字符串。

当你在C#中输入 "\\'" 时,第一个\转义第二个\(所以第二个\不被视为转义字符),并且'被视为普通的'(因为该字符串未用'界定)。


感谢您的详细解释,我会更加小心处理类似这样的问题。 - Sarawut Positwinyu

3

因为 "\" 也是C#的转义字符,所以我建议在字符串开始之前使用@特殊运算符,告诉C#不要处理转义字符。

例如:

ScriptManager.RegisterStartupScript(this, this.GetType(), "temp", @"alert('Can\'t delete this data because it is bound with rate plan');", true);

无论如何,我不认为单引号有什么意义。您可以通过使用双引号字符串符号来避免对该单引号进行转义:

ScriptManager.RegisterStartupScript(this, this.GetType(), "temp", "alert(\"Can't delete this data because it is bound with rate plan\");", true);

如果我没有记错,有很多 PHP 程序员贡献了 JavaScript 脚本,所以我不理解在 JavaScript 中滥用单引号的行为,因为这种语言会根据单引号或双引号字符串的不同而表现出不同的行为。

无论如何,您可以查看关于 JavaScript 中单引号和双引号的另一个问题:


谢谢,我对单引号和双引号没有太多的了解,感谢您指出这个问题,这样下次我就可以更好地使用它了 :) - Sarawut Positwinyu
绝对的,如果这些语言的“优势”是无用的,我认为在JavaScript或其他任何语言中使用它们是一种糟糕的方法 :) 很高兴知道它有用。 - Matías Fidemraizer

3
在C#字符串中,需要转义\,因为它是像\n等特殊前缀。您可能会发现使用verbatim string literal更容易,它不需要转义(除了""")。例如:
@"... can\'t ..."

请注意字符串文字之前的前导@,它表示使用替代转义规则。这也允许直接在字符串中添加换行符等,即:
@"foo
bar
blip"

1

当你使用\\时,它会在实际的JavaScript中转义为\,从而转义该字符。你实际上是进行了两次转义。


0

在动态客户端脚本中,名称中的单引号和撇号(例如O'Brian)通常会导致问题,因为它们会破坏脚本并允许插入恶意代码(也称为脚本攻击)。

我编写了以下用于代码后台的C#6扩展方法来解决这个问题:

public static class Extension
{
    public static string ToSQEscapedStringJS<T>(this T unescapedStr)
    {
        if (unescapedStr == null || unescapedStr.ToString() == "")
        {
            return "''";
        }
        // replace ' by @@@
        var escapedStr = (unescapedStr).ToString().Replace("'", "@@@"); 
        // JS code to replace @@@ by '
        string unEscapeSQuote = "replace(/@{3}/g, String.fromCharCode(0x27))"; 
        // add @@@ escaped string with conversion back to '
        return $"('{escapedStr}'.{unEscapeSQuote})"; 
    }
}

它的使用非常简单。考虑以下动态脚本示例:

// contains apostroph (aka single quote) and is dangerous for your script block
var name = "O'Brian"; 
var nameEscp = name.ToSQEscapedStringJS(); // creates JS expression from it
// building up the script
string strScript = 
   $"<script>window.opener.document.forms(0).{control.Value}.value = {nameEscp};</script>";
ClientScript.RegisterClientScriptBlock(this.GetType(), "anything", strScript);

请注意,nameEscp 已经被单引号包围,因此您可以安全地将其放在 = 之后。
诀窍在于字符串被转义,并在分配时立即解除转义(通过执行 JavaScript 表达式),即实时解除转义。
.value = ('O@@@Brian'.replace(/@{3}/g, String.fromCharCode(0x27));

将被插入的赋值表达式作为脚本发送给客户端。执行后,.value 包含 O'Brian


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