5

我已经阅读了许多关于此的帖子,但没有任何可靠的答案。这是我的代码:

// button creation
onew = document.createElement('input');
onew.setAttribute("type", "button");
onew.setAttribute("value", "hosts");
onew.onclick = function(){fnDisplay_Computers("'" + alines[i] + "'"); }; // ie
onew.setAttribute("onclick", "fnDisplay_Computers('" + alines[i] + "')"); // mozilla
odiv.appendChild(onew);

现在,setAttribute() 方法(带有 mozilla 注释)在 mozilla 中可以正常工作,但前提是它位于它上面的行之后。所以换句话说,它似乎只是默认为最后设置的那个。.onclick 方法(带有 ie 注释)在这两种情况下都不起作用,我是否使用不正确?

无论哪种方式,我都找不到在 IE 中完成这项工作的方法,更不用说两者了。我在使用 .onclick 方法时确实更改了函数调用,并且仅使用对警报函数的简单调用就可以正常工作,这就是为什么我认为我的语法不正确的原因。

长话短说,我无法让 onclick 参数在 IE/Mozilla 之间保持一致。

——尼古拉斯

4

4 回答 4

15

onew.setAttribute("类型", "按钮");

切勿在 HTML 文档上使用 setAttribute。IE 在很多情况下都犯了严重错误,而且 DOM-HTML 属性更短、更快且更易于阅读:

onew.type= 'button';

onew.onclick = function(){fnDisplay_Computers("'" + alines[i] + "'"); }; // IE

什么是“直线”?为什么要将其转换为字符串并用单引号括起来?看起来您正在尝试做一些令人发指的事情,涉及评估字符串中的代码(这就是您在下面的“onew.setAttribute”版本中所做的事情)。在字符串中评估 JavaScript 代码几乎总是错误的;像瘟疫一样避免它。在上述情况下,IE 应该和 Firefox 一样:它不应该工作。

如果 'alines[i]' 是一个字符串,我猜你想要做的是通过构造一个代码字符串来记住该字符串,该字符串将在 JavaScript 中评估为原始字符串。但:

"'" + alines[i] + "'"

是不够的。如果 'alines[i]' 中有撇号或反斜杠会怎样?

'O'Reilly'

你有一个语法错误和可能的安全漏洞。现在,你可以做一些费力和烦人的事情,比如:

"'" + alines[i].split('\\').join('\\\\').split("'").join("\\'") + "'"

尝试转义字符串,但它很丑陋并且不适用于其他数据类型。你甚至可以让 JavaScript 为你做这件事:

uneval(alines[i])

但并非所有对象都可以转换为可评估的 JavaScript 源字符串;基本上整个方法注定要失败。

如果您只想让 onclick 回调调用带参数的函数,通常的做法是直接编写代码:

onew.onclick= function() {
    fnDisplay_Computers(alines[i]);
};

通常这会起作用,并且是您想要的。但是,您可能在此处遇到了轻微的皱纹,这可能会让您感到困惑,以考虑使用弦乐的古怪方法。

即,如果在这种情况下“i”是封闭“for”循环的变量,则对“alines[i]”的引用不会像你想象的那样做。当点击发生时,回调函数将访问“i”——这是循环完成之后。此时,“i”变量将保留其在循环结束时的任何值,因此“alines[i]”将始终是“alines”的最后一个元素,无论单击哪个“新”。

(请参阅如何在 ActionScript 3 (AS3) 中修复闭包问题,了解有关此问题的一些讨论。它是 JavaScript 和 Python 中与闭包混淆的最大原因之一,总有一天应该在语言级别上修复。)

您可以通过将闭包封装在自己的函数中来解决循环问题,如下所示:

function callbackWithArgs(f, args) {
    return function() { f.apply(window, args); }
}

// ...

onew.onclick= callbackWithArgs(fnDisplay_Computers, [alines[i]]);

在更高版本的 JavaScript 中,您将能够简单地说:

onew.onclick= fnDisplay_Computers.bind(window, alines[i]);

如果您希望能够在今天的浏览器中使用“Function.bind()”,您可以从Prototype框架中获得一个实现,或者只使用:

if (!('bind' in Function.prototype)) {
    Function.prototype.bind= function(owner) {
        var that= this;
        var args= Array.prototype.slice.call(arguments, 1);
        return function() {
            return that.apply(owner,
                args.length===0? arguments : arguments.length===0? args :
                args.concat(Array.prototype.slice.call(arguments, 0))
            );
        };
    };
}
于 2009-04-14T20:32:24.550 回答
6

我通常使用类似的东西:

onew.onclick = new Function("fnDisplay_Computers('" + alines[i] + "')");

这应该适用于 IE e Firefox。

于 2009-04-14T19:18:52.170 回答
1

基于 Mozilla 的浏览器使用addEventListener()带“ ”的函数click作为参数,IE 使用带“ ”的函数;我发现最好使用 try/catch 语句,例如:typeattachEvent()onclicksEvent

try {
  onew.attachEvent("onclick", //For IE
                   function(){fnDisplay_Computers("'" + alines[i] + "'"); });
}
catch(e) {
  onew.addEventListener("click", //For Mozilla-based browsers
                   function(){fnDisplay_Computers("'" + alines[i] + "'"); },
                   false);
}
于 2009-04-14T19:17:48.863 回答
0

我认为#3抗议太多了。在很多情况下,我正在动态构建一个表并且需要将参数传递给回调函数。这不是类型安全问题,因为我的变量 parm 是相关表行的整数索引。这是具有似乎跨浏览器兼容的变量和固定参数的代码:

for (i = 0; i < arrTableData.length; i++) {
    eleTR = objTable.insertRow(i + 1);
    cell = eleTR.insertCell(0);
    cell.width = "21";
    var myElement = document.createElement('img');
    myElement.setAttribute('src', 'images/button_down.gif');
    myElement.setAttribute('alt', 'Move item down');
    myElement.onclick = new Function('moveItem(' + i + ',0)');
    cell.appendChild(myElement);
}
于 2010-04-24T16:21:45.493 回答