代码之家  ›  专栏  ›  技术社区  ›  Nick McCurdy

极其恼人的JavaScript数组/对象错误

  •  2
  • Nick McCurdy  · 技术社区  · 14 年前

    基本上,我正在重写我的一个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 回复  |  直到 14 年前
        1
  •  4
  •   Tim Down    14 年前

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

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

    这是用 slice 所有数组通用的方法 Array.prototype 创造一个真正的 Array 数组中的对象 arguments . call() (所有函数的方法)用于调用 方法与 this 价值 论据 没有参数,这会复制 变成一个新的阵列。这可能看起来有点迂腐,但实际上是被设计成语言的:请看下面的注释 section 15.4.4.10 of the ECMAScript 3rd Edition spec .

    此外,在一个函数中,还提供了 论据 对象作为变量,因此您不需要像现在这样作为函数对象的属性来访问它。在你的情况下,使用 论据 而不是 panel.arguments .

        2
  •  4
  •   Cᴏʀʏ bcherry    14 年前

    你可以让它简单得多(清理格式、分号等):

    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);
    

    或者 ,因为现在它在语法上非常简单,所以您最好只创建两个单独的函数,这样您的代码就很简单,并且您可以从函数名中准确地知道它要做什么:

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

    最后,如果你不担心通过CSS来完成,你可以把你的脚本缩短到这个,这再清楚不过了:

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

    干杯!