原型回调函数替换'这'价值

Prototype callback function replace 'this' value

本文关键字:价值 回调 函数 原型 替换      更新时间:2023-11-12

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

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

好吧,简而言之,这个函数类似于排序函数,只是它通过多级对象进行排序,并且我指定它需要按哪些键进行排序。
问题是,我从来没有实际替换或更改"this"值,这意味着这个函数实际上什么都不做。例如:

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

它不会在sortArr(1)调用之前或之后更改arr。然而,当我把alert(newArr)放在函数返回之前时,它表明它确实重新排序了。所以,我的问题是;如何替换回调函数中的this值,或者至少返回正确的/新的数组?提前谢谢。

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

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循环,就像我在上面的代码片段中所做的那样。

实现后,将返回一个新数组。如果你想用新的结果替换原来的数组,你必须明确地这样做:

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

但听起来这不是你想做的。

var newArray = [{},"Bob",32].sortArr();

不要把你的return语句看作是回到函数的顶部。。。…把它想象成从左手边出去。

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

我的意思是:

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将向原始对象添加名称:"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="Bob";obj=localObj;}

    addBob3(externalObj);

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

obj.name = localObj.name;

这将把数据发送回原始对象(即:从函数顶部)。有些人认为这种做法很糟糕,因为如果你有几十个这样的就地修改函数,当你进入10000行程序时,很难判断哪些对象被哪些函数修改了。

现在不要太担心。

其他方法:

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

var externalObj = { property1 : "something" },
newObj = addBob4(externalObj);

现在,返回值将输出到函数调用的LEFT。newObj将是一个与externalObj完全相似的对象,除了您对副本进行的新添加。

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

处理"这个"有点棘手。如果它是一个对象,您只需执行"this.name=‘Bob’;"即可完成。

在数组的情况下,您需要第三个循环,基本上清空this[0]-this.length-1],然后用newArr中的值填充this[0]–this[newArr.length-1]。因为JavaScript不会让你把"this"分解成"this=X"语句。