javascript - Firefox 上 Greasemonkey 脚本中 JavaScript 中的类型强制和字符串连接问题

标签 javascript firefox string greasemonkey type-conversion

我正在创建一个 GreaseMonkey 脚本来改进 Stack Overflow 使用的 10k 工具的用户界面。我遇到了一个无法重现且坦率地说很奇怪的问题,这让我和 JavaScript room 中的其他人感到困惑。在 SO Chat 上。 several lengthy 之后我们还没有找到原因debugging sessions .

可以找到有问题的脚本here . Source - Install


问题出现在第 85 行,'vodoo' 注释之后的行:

return (t + ' (' + +(+f.offensive + +f.spam) + ')');

可能看起来有点奇怪,但是两个变量和内部括号前面的+是类型强制,里面的+是加法,其他的用于连接。

没有什么特别的,但细心的读者可能会注意到内部括号上的类型强制是不必要的,因为两者都已经被类型强制转换为数字,并且当它们连接成字符串时类型强制结果是无用的。不是这样!删除 + 会破坏脚本,导致 f.offensivef.spam 被连接起来而不是加在一起。

进一步添加 console.log 只会让事情变得更加困惑:

console.log(f.offensive + f.spam); // 50
console.log('' + (+f.offensive + +f.spam)); // 5, but returning this yields 50 somehow
console.log('' + (+f.offensive + +f.spam) + ''); // 50

来源:https://chat.stackoverflow.com/transcript/message/203261#203261


问题是这是不可重现的——运行像这样的脚本

console.log('a' + (+'3' + +'1') + 'b');

在 Firebug 控制台中产生正确的结果,正如

(function(){
    return 'a' + (+'3' + +'1') + 'b';
})();

即使提取大块代码并在控制台中运行它们也不会重现此错误:

$('.post-menu a[id^=flag-post-]').each(function(){
    var f = {offensive: '4', spam: '1'};
    
    if(f){
        $(this).text(function(i, t){
            // Vodoo - please do not remove the '+' in front of the inner bracket
            return (t + ' (' + +(+f.offensive + +f.spam) + ')');
        });
    }
});

聊天室中的 Tim Stone 有 reproduction instruction对于那些低于 10k 的人。


这个错误只出现在 Firefox 中 - Chrome 似乎没有出现这个问题,让我相信这可能是 Firefox 的 JavaScript 引擎或 Greasemonkey 附加组件的问题。我说得对吗?

我可以在JavaScript room中找到如果您需要更多详细信息和/或想要对此进行讨论。

最佳答案

作为用户脚本进程的一部分,一个<script>使用通过调用 toString() 检索到的代码将标签注入(inject)到页面中在您定义的功能上。通常这会很好,但似乎 Firefox 3.6.13 使用的 javascript 引擎中存在一个错误,该错误重新定位表达式中的括号,导致在 toString() 时以非常不同的方式对其进行评估。 -ified 函数被处理。

为了说明这个问题,我们可以在Firebug中运行如下代码:

function f() { var a = '', b = '1', c = '2'; return a + '(' + (+b + +c) + ')'; };
f.toString();

这给了我们这个输出:

function f() {
    var a = "", b = "1", c = "2";
    return a + ("(" + + b + + c + ")");
}

您会注意到返回表达式已被修改。括号已被重新定位到之前位于它们之外的字符串之外,导致变量 bc被强制转换为字符串并连接起来。这给出了意想不到的结果,因为预期的添加从未发生。不幸的是,即使使用 Number() 也会出现这种行为。或 parseInt()胁迫bc .

有几个小的修改可以改变这个,但最清楚的是预先将加法的结果保存到一个变量中:

$(this).text(function(i, t){
    var c = +f.offensive + +f.spam;
    return (t + ' (' + c + ')');
});

幸运的是,这个问题似乎没有出现在 Firefox 4 beta 中,所以希望这个问题已经得到解决。另外,Matthew Flaschen已经慷慨地继续前进并且filed a bug report (标记为 559438 的副本),以便开发人员在任何一种情况下都意识到这个问题。

关于javascript - Firefox 上 Greasemonkey 脚本中 JavaScript 中的类型强制和字符串连接问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4469044/

相关文章:

javascript - jQuery Modal - 按钮操作

javascript - 部署到 Cloud Foundry 的应用程序无法启动

javascript - 你能测试浏览器对 -moz-linear-gradient 的支持吗?

Python 和 Selenium : Force no download window

javascript - 使用 FileReader 的 readAsBinaryString 和 readAsText 之间的区别

php - 第一次尝试无法登录

javascript - 扩展组件以获取 firefox 历史记录和书签中的访问次数?

python - 仅从python中的字符串中获取所需的部分

java - 我可以使用正则表达式或其他方式更快地执行此操作吗?

javascript - 选择 id 和 name 中带有方括号的复选框