1

好吧,我偷偷怀疑我忽略了一些非常简单的东西,但是我遇到了以下代码的问题:

Array.prototype.sortArr = function (skey)
{
    var vals = new Array();
    for (key in this)
    {
        if (typeof(this[key][skey]) != 'undefined')
        {
            vals.push((this[key][skey]+'').toLowerCase());
        }
    }
    vals.sort();

    var newArr = new Array();
    for (i=0;i<vals.length;i++)
    {
        for (key in this)
        {
            if (typeof(this[key][skey]) != 'undefined')
            {
                if ((this[key][skey]+'').toLowerCase() == vals[i])
                {
                    newArr.push(this[key]);
                    break;
                }
            }
        }
    }
    return newArr;
}

好的,简而言之,这个函数类似于 sort 函数,不同之处在于它通过多级对象进行排序,并且我指定了它需要排序的键。
问题是我从未真正替换或更改“this”值,这意味着这个函数实际上并没有做任何事情。例如:

var arr = new Array(new Array(1,5),new Array(2,0));
arr.sortArr(1);

它不会改变通话arr之前或之后的情况sortArr(1)。但是,当我alert(newArr)在函数返回之前放置一个权利时,它表明它实际上确实重新排序了。所以,我的问题是;如何替换this回调函数中的值或至少返回正确/新数组?提前致谢。

4

3 回答 3

1

要在方法结束时修改当前数组,您需要像这样分配给它的元素,在函数结束之前将所有元素复制到当前对象的数组中:

this.length = newArr.length;
for (var i = 0; i < newArr.length; i++) {
    this[i] = newArr[i];
}

你也可以.splice()这样使用:

newArr.unshift(this.length);     // how many items to remove for .splice()
newArr.unshift(0);               // index for .splice() operation
this.splice.apply(this, newArr); // add the newArr elements

仅供参考,在数组上使用该构造通常是不正确的,for/in因为除了数组元素之外,它还会迭代对象上的属性,这通常会使您感到困惑。如果您想迭代数组中的项目,请使用传统的 for 循环,就像我在上面的代码片段中所做的那样。

于 2012-07-19T04:42:28.607 回答
0

当您实现它时,您将返回一个新数组。如果您想用新结果替换原始数组,则必须明确这样做:

var arr = new Array(new Array(1,5),new Array(2,0)); 
arr = arr.sortArr(1);

但听起来那不是你想要做的。

于 2012-07-19T04:48:46.637 回答
0
var newArray = [{},"Bob",32].sortArr();

想想你的 return 语句不是回到函数的顶部............把它想象成离开左侧。

所以当你定义你的函数时,你把你的参数放在你的参数的位置。如果要按原样对传入的对象进行排序,则需要按原样对原始对象执行操作,而不保存对象的副本。

我的意思是:

function addBob (obj) {
    obj.name = "Bob";
    return undefined;
    // any fn without a return mentioned returns undefined, anyway.
    // I just put this here for reference.
}

此版本的 addBob 将 name : "Bob" 添加到原始对象。

function addBob2 (obj) {
    bobject = obj;
    bobject.name = "Bob";
    return undefined;  // again, if you don't state a return, that's what you get
}

好的。现在我们遇到了问题。你能看见它吗?

您已将一个对象放入函数的顶部,并保存了对象的本地副本(有时,这是一件好事……但不是在这里)。

然后你修改了你的副本。

你认为你已经完成了。但你不是。没有改变。为什么?

因为您没有将更改保存回原始文件。可能有两种方法可以做到这一点:

  1. 函数 addBob3(obj) { var localObj = obj; localObj.name = "鲍勃"; 对象 = 本地对象;}

    addBob3(externalObj);

此函数旨在保存本地副本以进行计算,但是一旦这些计算完成,它就会覆盖原始对象或对象的属性——即:

obj.name = localObj.name;

这会将数据发送回原始对象(即:在函数顶部之外)。有些人认为这是不好的做法,因为如果您有几十个这样的就地修改函数,当您进入 10,000 行程序时,很难分辨哪些对象已被哪些函数修改。

现在不要太担心。

一种方法:

function addBob4(obj) {
    var localObj = obj;
    localObj.name = "Bob";
    return localObj;
}


var externalObj = { property1 : "something" },

newObj = addBob4(externalObj);

现在,您已经将返回值传到了函数调用的LEFT。newObj 将是一个与 externalObj 完全相同的对象,除了您对副本所做的新添加。

因此,如果您在变量中捕获返回,函数可以从左侧退出。如果您直接就地修改传入的对象,则在函数退出后,这些编辑将应用于原始对象/对象。

使用“this”有点棘手。如果它是一个对象,你可以做“this.name = 'Bob';” 你就完成了。

对于您的数组,您需要第三个循环,基本上清空 this[0] - this[this.length - 1],然后填充 this[0] - this[newArr.length - 1],使用来自 newArr 的值。因为 JavaScript 不会让您分解“this”并将其变成“this = X”语句。

于 2012-07-19T05:27:18.887 回答