0

我有一个小函数可以从对象中生成 URL 参数:

function MkArgs(o) {
    var ret = '?';
    for (var i in o) {
        ret += i + '=' + escape(o[i]) + '&';
    }
    return ret.substr(0, ret.length - 1);
}

然后我可以这样称呼:

MkArgs({
    protocol: 'wsfederation',
    realm: 'https://www.x.com/',
    fedRes: 'Home/FederationResult',
    context: '~/Home/FAQ',
    version: '1.0',
    callback: '?'
});

产生以下内容:

?protocol=wsfederation&realm=https%3A//www.x.com/&fedRes=Home/FederationResult&context=%7E/Home/FAQ&version=1.0&callback=%3F

一切都很好,除了我不希望最后一个参数转义,即我想要:

callback=?

代替

callback=%3F

有什么办法可以在字符串中指出这一点吗?我试过'\?'了,但没有这样做,也没有找到任何关于如何保护一段字符串免于逃逸的参考资料......

  • e
4

5 回答 5

1

escape 或 encodeURIComponent 函数没有任何“跳过”某些字符的方式。因此,您所能做的就是避免在不想编码时调用编码函数,或者替换您不想编码的字符,调用编码,然后再放回原始字符。

如果您想跳过转义特定键的整个值,您可以只检查您不想转义的特定键并像这样适当地处理:

function MkArgs(o) {
    var ret = '?';
    for (var i in o) {
        var val = o[i];
        if (i != "callback") {
            val = encodeURIComponent(val);
        }
        ret += i + '=' + val + '&';
    }
    return ret.substr(0, ret.length - 1);
}

如果你只想跳过某些字符,那么你可以用一些独特的序列替换它们,转义然后放回去:

function MkArgs(o) {
    var ret = '?';
    for (var i in o) {
        var val = o[i];
        if (i == "callback") {
            val = val.replace(/\?/, "--xx--");  // replace with unique sequence
            val = encodeURIComponent(val);
            val = val.replace(/--xx--/, "?");   // put orig characters back
        } else {
            val = encodeURIComponent(val);
        }
        ret += i + '=' + val + '&';
    }
    return ret.substr(0, ret.length - 1);
}

仅供参考,请注意我已切换到encodeURIComponent()建议使用已弃用的方法escape(),因为escape()它不适用于非 ascii 字符。

于 2011-08-08T19:11:02.367 回答
1

MkArgs 函数是你自己的;将其更改为包含逃生机制。不过,我建议不要使用反斜杠。如果这只是您自己的代码,那么放入一个骇人听闻的特殊情况就足够了。

于 2011-08-08T19:17:36.790 回答
1

这是一个非常特殊的情况。也许你应该改变你的功能:

function MkArgs(o, isJSONP) {
    var ret = '?';
    for (var i in o) {
        var val = o[i];
        val = escape(val);
        ret += i + '=' + val + '&';
    }
    return ret.substr(0, ret.length - 1) + isJSONP ? '&callback=?':'';
}

并称之为:

MkArgs({
  protocol: 'wsfederation',
  realm: 'https://www.x.com/',
  fedRes: 'Home/FederationResult',
  context: '~/Home/FAQ',
  version: '1.0'
}, true);
于 2011-08-08T19:27:41.717 回答
0
function MkArgs(o) {
    var ret = '?';
    var lastEl = '';
    for (var i in o) {
        ret += i + '=' + escape(o[i]) + '&';
        lastEl = o[i];
    }
    return ret.substr(0, ret.length - 1 - lastEl.length) + lastEl;
}

这适用于对象中的最后一个元素。

编辑:似乎在经典for in循环中,javascript没有精确的循环对象道具的顺序,因此不能保证上述解决方案有效。
在这种情况下,您有 2 个解决方案:

  • 如果您知道要“保护”哪个属性免于转义,则应在循环中检查该道具,特别是不要对其进行转义:

    for (var i in o) {
         if(i=="myProp")
         // unescape
         else
         // escape
    }
    
  • 如果您现在没有该属性,但您只想将最后一个添加到查询中,您可以执行以下操作(在构建查询之后):

    var q = MkArgs(o);
    var parts = q.split('=');
    var toUnescape = parts[parts.length-1];
    q = q.substring(0,q.length - toUnescape.length) + unescape(toUnescape);
    
于 2011-08-08T19:32:44.080 回答
0

感谢大家的回复。我最终做的是:

function MkArgs(o) {
    var ret = '?';
    for (var i in o) {
        ret += i;
        if (o[i]) ret += '=' + escape(o[i]);
        ret += '&';
    }
    return ret.substr(0, ret.length - 1);
}

然后像这样称呼它:

MkArgs({
    protocol: 'wsfederation',
    realm: 'https://www.x.com/',
    fedRes: 'Home/FederationResult',
    context: '~/Home/FAQ',
    version: '1.0',
    'callback=?': null
});

这样我就不依赖于价值观,而是依赖于区分的关键。不是很漂亮,但这是我能想到的最好的

于 2011-08-08T22:12:08.753 回答