非常恼人的JavaScript数组/对象错误

时间:2010-11-26 18:20:36

标签: javascript arrays object

基本上,我正在重写我的一个Web应用程序的一部分。我有一个脚本可以同时折叠界面的部分或全部面板,另一个脚本可以对它们进行编码。

然而,我的旧功能看起来非常难看,并且打字很烦人而且不够强大:

function collapse_all()
{
    document.getElementById("panel_1").style.display="none"
    document.getElementById("panel_2").style.display="none"
    document.getElementById("panel_3").style.display="none"
}
function expand_all()
{
    document.getElementById("panel_1").style.display=""
    document.getElementById("panel_2").style.display=""
    document.getElementById("panel_3").style.display=""
}

现在我有了这个:

function panel() //first variable in argument is collapse or expand, all others are panels to act on
{
    var panels = panel.arguments
    alert(typeof panel.arguments)
    var mode = panels.shift() //here's my problem
    if(mode=="collapse") {mode="none"}
    if(mode=="expand") {mode=""}
    var items = panels.length
    for (i = 0;i < items;i++) {document.getElementById(panels[i]).style.display=mode}
}

panel("collapse","panel_1","panel_2","panel_3")

我有一个问题。 Firebug告诉我panels.shift()不是一个函数。通过一些谷歌搜索,我设法找出panel.arguments不是一个数组而是一个对象,所以我不能在它上面使用数组方法。我真的很困惑我如何将对象转换为数组或找到另一种解决方法,因为我对JavaScript对象几乎一无所知。一些示例代码将受到高度赞赏。

2 个答案:

答案 0 :(得分:4)

您可以将arguments对象转换为如下数组:

var argsArray = Array.prototype.slice.call(arguments);

这样做是通过slice使用所有数组通用的Array.prototype方法从类似数组的Array创建一个真正的arguments对象。 call()(所有函数的方法)用于调用此slice方法this arguments并且没有参数,这样可以复制所有函数this的元素到一个新数组中。这可能看似狡猾或骇人听闻,但它实际上是用语言设计的:请参阅section 15.4.4.10 of the ECMAScript 3rd Edition spec底部的注释。

此外,在函数中,您将arguments对象作为变量提供,因此您不需要像操作那样将其作为函数对象的属性进行访问。在您的情况下,只需使用arguments而不是panel.arguments

答案 1 :(得分:4)

你可以更简单(清理你的格式,分号等):

function panel() 
{
    var panels = Array.prototype.slice.call(arguments);
    var displayMode = (panels[0] == "collapse" ? "none" : "");

    for (var i = 1; i < panels.length - 1; i++) 
    {
        document.getElementById(panels[i]).style.display = displayMode;
    }
}

此外,如果您正在重写您的应用程序,那么可能是考虑使用jQuery等内容的好时机。您可以为每个面板指定一个特定的类名,并将代码缩减为:

function panel(hide)
{
    $('.className').css({ display: (hide ? 'none' : '') });
}

你可以这样使用:

panel(true); // or
panel(false);

,因为现在它在语法上非常简单,你可能只需要创建两个独立的函数,这样你的代码就很简单了,而且你只知道它将从函数名中做些什么:< / p>

function showPanels() {
    $('.className').css({ display: '' });
}

function hidePanels() {
    $('.className').css({ display: 'none' });
}

最后,如果你不担心通过CSS来做,你可以真正缩短你的脚本,这不能更清楚:

function showPanels() {
    $('.className').show();
}

function hidePanels() {
    $('.className').hide();
}

干杯!