5

I am trying to extend the Array prototype:

Array.prototype.rotate = function() {
  var arr = [];
  for (var i = 0; i < this[0].length; ++i) {
    arr[i] = [];
    for (var j = 0; j < this.length; ++j) {
      arr[i].push(this[j][i])
    }
  }
  this = arr;
  return arr;
}

Totally dandy, until this = arr. That bombs out.

How do I re-assign the this property of a prototypal function? I want the hells to do with the previous array configuration.

EDIT

Why am I doing it this way? I want it to behave like other array functions. For example, this works:

myArray.pop();

I don't need to do this:

myArray = myArray.pop();

ANOTHER EDIT

I did this to solve it, but it seems stupid:

Array.prototype.rotate = function() 
{
  var arr = [];
  var len = this[0].length;
  for (var i = 0; i < len; ++i) {
    arr[i] = [];
    for (var j = 0; j < this.length; ++j) {
      arr[i].push(this[j][i])
    }
  }
  for (var i = 0; i < this.length; ++i) {
    delete this[i];
  }
  for (var i = 0; i < arr.length; ++i) {
    this[i] = arr[i];
  }
  return arr;
}

This would work, but, in an example, when rotating this array:

[[1, 1], [2, 2], [3, 3]]

I would get:

[[1, 2, 3], [1, 2, 3], ]

See that little blank third item? Yeah - that caused me problems.

dthree
  • 19,847
  • 14
  • 77
  • 106
  • 6
    You cannot explicitly assign a value to `this`. What is that supposed to accomplish in this case? – Matt Ball May 06 '14 at 23:29
  • 1
    Avoid mutation, simply assign the returned array to a new variable. – elclanrs May 06 '14 at 23:29
  • Well, how does array.pop() do it? It doesn't require returning the value to a new array! I just changes the array! – dthree May 06 '14 at 23:30
  • You don't even need that line in question – Sunny Patel May 06 '14 at 23:31
  • Yes, there are methods that mutate the array, but you don't need it. I wouldn't even extend the prototype, I'd make my own function that takes an array. – elclanrs May 06 '14 at 23:31
  • 1
    How does `.pop` do it? `var value = this[this.length - 1]; this.length -= 1; return value;`, or something like that. – Felix Kling May 06 '14 at 23:33
  • 1
    ["The `pop()` method removes the last element from an array and returns that element."](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop) It does **not** change the "this" array beyond removing the last value. – Matt Ball May 06 '14 at 23:33
  • 2
    I think what you're looking for is a `zip` though, check http://stackoverflow.com/questions/4856717/javascript-equivalent-of-pythons-zip-function – elclanrs May 06 '14 at 23:37
  • 1
    Good point, @elclanrs. I think that's an `underscore.js` function now that I look at it - no? – dthree May 06 '14 at 23:38

3 Answers3

9

Although you cannot overwrite this, you can most certainly set the value of the working array to the array you've built out in your function. Something like this:

Array.prototype.rotate = function() {
  var arr = [];
  for (var i = 0; i < this[0].length; ++i) {
    arr[i] = [];
    for (var j = 0; j < this.length; ++j) {
      arr[i].push(this[j][i])
    }
  }
  this.length = 0; //empty the array
  this.push.apply(this, arr); //push all of the elements from arr onto this
  return arr;
}
Sean Johnson
  • 5,567
  • 2
  • 17
  • 22
  • Thank you for being helpful! This seems like it would solve it. – dthree May 06 '14 at 23:33
  • `this.length = 0` only abstracts it being empty though I think. If the original array had more elements than `arr` there could be remnants left behind. – Travis J May 06 '14 at 23:34
  • 1
    @TravisJ: The specification says every at an index > length should be removed. Somewhere in here: http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.5.1 (however, I think there were cases with some browsers where this didn't work properly... can't remember exactly though). – Felix Kling May 06 '14 at 23:34
0

You can't edit this, but you can edit this[i][j], so copy your temporary array into this with a loop.

Meredith
  • 844
  • 6
  • 17
0

As @Meredith said, if you modify this instead of a new array, you'll have the result you expect. the following test worked for me :

Array.prototype.rotate = function(){
    var a = this[0];
    this[0] = this[1];
    this[1] = a;
};

var test = [1,2];
test.rotate();
console.log(test); // [2,1]
Xeltor
  • 4,626
  • 3
  • 24
  • 26