0

Is there any way to retrieve the element that was most recently added/inserted to an array in Javascript?

To be crystal clear, I don't mean the last element in the array, I mean the element that was last inserted to some arbitrary position.

If there's no way of doing it without explicitly storing the last index upon insertion, then I'll look for the simplest answer based on that.

For those asking how the element was added, let's say I've done this:

// Insert new_element at index, shift other elements to accomodate it
existing_array.splice(index, 0, new_element);
s-low
  • 706
  • 2
  • 8
  • 21
  • 2
    Depends how do you insert into the array? do you use push or arr[id] = element – Marc Rasmussen Sep 09 '16 at 13:45
  • What is the function who added/inserted element ? – user2226755 Sep 09 '16 at 13:45
  • No, there is not, not natively at least, javascript doesn't keep track of when something was inserted, just where it was inserted. On the other hand, you most likely shouldn't be inserting to arbitrary positions in an array. – adeneo Sep 09 '16 at 13:46
  • You can compare original array with the adjusted array and see which element is new – Depzor Sep 09 '16 at 13:46
  • 1
    @Depzor you'd need to hold a copy of the second most recent version of the array, and keep it up to date. At that point, it's quicker and more space efficient to just track the index of the last updated value – StephenTG Sep 09 '16 at 13:47
  • Do you care about modifications to elements, or just values added where there was no defined value before? – StephenTG Sep 09 '16 at 13:48
  • there is no way to do this, the only possible solution coming to my mind is that you can keep a cookie in browser and whenever you are adding element in an aaray update the value of that cookie. Retrieve the cookie when you want and you can get the last element inserted in an array. – kshitij Sep 09 '16 at 13:49
  • 1
    Have edited the question to include an example of how the element might have been inserted – s-low Sep 09 '16 at 13:50
  • 1
    And again, no, there is nothing keeping track of "latest added" in an array, you'd have to do it yourself. – adeneo Sep 09 '16 at 13:52
  • 1
    you can do this with ES 6 proxies , see my answer – Vladu Ionut Sep 09 '16 at 14:01
  • It's easy to modify splice function. – user2226755 Sep 09 '16 at 14:20
  • Who on earth is downvoting this question? Just because there isn't actually a direct, elegant answer doesn't mean it's a bad question - in fact, surely it suggests it's a good question? – s-low Sep 09 '16 at 14:21

4 Answers4

1

There is no way.

you must keep track of the last inserted position.

Here is a simple code sample :

Array.prototype.lastIndex = -1;

// edit that to match your actual insertion method
function insertInArray(arr, val, index) {
  arr[index] = val;
  arr.lastIndex = index;
}

var a = [1, 2, 3];
var b = [4, 5, 6];

console.log("a before: " + a.lastIndex);
console.log("b before: " + b.lastIndex);

insertInArray(a, 1, 2);


console.log("a after: " + a.lastIndex);
console.log("b after: " + b.lastIndex);
Regis Portalez
  • 4,675
  • 1
  • 29
  • 41
1

Theoretically you could extend the Array prototype to give you this information:

Array.prototype.lastAdded = {
 index: -1,
 value: null
};
Array.prototype.add = function (element, index) {
    //If no index, put at back
    if (index === void 0) {
  index = this.length;
    }
    //Add value
    this[index] = element;
    //Set "lastAdded";
    this.lastAdded = {
  index: index,
  value: this[index]
    };
}
var list = [1, 2, 3, 4, 5, 6, 7, 8, 9];

list.add(10);
console.log(list.lastAdded);

list.add(2, 2);
console.log(list.lastAdded);

EDIT 1 - Doing it with a wrapper object

Here is an example where you leave the Native Objects be:

console.clear();
var ArrayWrapper = (function() {
  function ArrayWrapper(array) {
    if (array === void 0) {
      array = [];
    }
    this.array = array;
    var self = this;
    for (var key in Object.getOwnPropertyNames(Array)) {
      var element = Object.getOwnPropertyNames(Array)[key];
      (function(el) {
        self[el] = function() {
          //make a clone
          var oldArr = JSON.parse(JSON.stringify(self.array));
          self.array[el].apply(self.array, arguments);
          //If a change has occured
          var change = false;
          for (var key in self.array) {
            if (self.array.hasOwnProperty(key)) {
              if (!oldArr.hasOwnProperty(key)) {
                //New key
                self.lastChange = key;
                change = true;
                break;
              } else if (oldArr[key] != self.array[key]) {
                //Modified key
                self.lastChange = key;
                change = true;
                break;
              }
            }
          }
          //If it wasn't added or modifed we test for deleted
          if (!change) {
            for (var key in oldArr) {
              if (oldArr.hasOwnProperty(key)) {
                if (!self.array.hasOwnProperty(key)) {
                  //deleted key
                  self.lastChange = key;
                  break;
                }
              }
            }
          }
        };
      })(element);
    }
  }
  return ArrayWrapper;
}());
var xarray = new ArrayWrapper([1, 2, 3]);
console.log("current array", xarray.array);
xarray.push(1232);
console.log("change at", xarray.lastChange);
console.log("current array", xarray.array);
xarray.splice(0, 1, 8);
console.log("change at", xarray.lastChange);
console.log("current array", xarray.array);

I weren't kidding when i said it would be more complicated.

This method allows you to create a layer between you and the native functions of Array without actually touching said functions. This way the native object stays the same.

This could be used to store reusable array functions (like very unique sort or filter methods) or, as in this case, for containing meta-data about the array it wraps around.

Emil S. Jørgensen
  • 6,216
  • 1
  • 15
  • 28
  • creative solution – Depzor Sep 09 '16 at 13:59
  • [Why is extending native objects a bad practice?](http://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice) – adeneo Sep 09 '16 at 14:01
  • @adeneo i agree, but the alternative would be even more complicated. – Emil S. Jørgensen Sep 09 '16 at 14:02
  • I like this solution - but hesitant to accept is as the answer if extending the array prototype really is that much of a sin? – s-low Sep 09 '16 at 14:03
  • 1
    @s-low Messing with the prototype in a way not aligning with the standards is usually bad because it might adversely effect other scripts' performance. That being said, writing wrapper objects as my example above can also be very cumbersome so you need to pick you fights. If it is **REALLY** important for you that **ALL ARRAYS** can do this then go for `prototype`. However, if only a few select arrays needs this functionality, then your better of with a wrapper. ... or simply a related variable. – Emil S. Jørgensen Sep 09 '16 at 14:54
0

You can do this with the ES6 Proxies

See the bellow snippet

var arrayChangeHandler = {
  lastChangedIndex :undefined,
  get: function(target, property) {
     return   (property == "lastChangedIndex") ? this.lastChangedIndex :target[property];
  },
  set: function(target, property, value, receiver) {
     target[property] = value;
     (property!=="length") && (this.lastChangedIndex = property);
     return true;
  }
};

var myArray = new Proxy([1,2,3,4,5,6,7,8,9], arrayChangeHandler);
myArray[5] = 0;
myArray[7] = 3;
console.log(myArray.lastChangedIndex) ;
myArray[1] = 2;
myArray[4] = 4;
console.log(myArray.lastChangedIndex) ;
myArray.push(10);
myArray.push(11);
myArray.push(14);
console.log(myArray.lastChangedIndex) ;
myArray.splice(9,0,22);
console.log(myArray.lastChangedIndex) ;
Vladu Ionut
  • 8,075
  • 1
  • 19
  • 30
0

var existing_array = [50, 51, 52, 53, 54];

var origin_splice = existing_array.splice;
existing_array.splice = function splice(index) {
    origin_splice.apply(this, [].slice.call(arguments));
    this.splice_lastIndex = index;
};

existing_array.splice(3, 0, "ok");

console.log(existing_array); // Array [ 50, 51, 52, "ok", 53, 54 ]
console.log(existing_array.splice_lastIndex); // 3
user2226755
  • 12,494
  • 5
  • 50
  • 73