Search code examples
javascriptprototypejsthis

Prototype callback function replace 'this' value


Alright, I have the sneaking suspicion that I am overlooking something really simple, but I am having an issue with the following code:

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

Okay, in a nutshell, this function is similar to the sort function with the exception that it sorts through a multi-level object and I specify which keys it needs to sort by.
The issue is that I never actually replace or alter the 'this' value, meaning that this function doesn't actually do anything. For example:

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

It will not change the arr from before or after the sortArr(1) call. However, when I put an alert(newArr) right before the return of the function, it shows that it actually did reorder. So, my question is; how do I replace the this value in the callback function or at least return the proper/ new array? Thanks in advance.


Solution

  • To modify the current array at the end of your method, you would need to assign to its elements like this, copying all the elements into the current object's array before the end of the function:

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

    You could also use .splice() like this:

    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
    

    FYI, it's not generally correct to use the for/in construct on arrays because it will iterate properties on the object too in addition to array elements and that will often foul you up. If you want to iterate the items in the array, use the traditional for loop like I did in my code snippet above.