Is there a way to replace the content of an array and still maintain a reference to it without losing the original reference? I want to avoid simply reassigning the array like this:
var arr1 = [1,2,3];
var referenceToArr1 = arr1;
var arr2 = [4,5,6];
arr1 = arr2;
// logs: [4,5,6] false
console.log(arr1, arr1===referenceToArr1);
// logs [1,2,3]
console.log(referenceToArr1);
In this scenario, arr1
is updated with the contents of arr2
, but the reference in referenceToArr1
is lost as it still points to the original arr1
.
To preserve the reference, you can do it like this:
var arr1 = [1,2,3];
var referenceToArr1 = arr1;
var arr2 = [4,5,6];
arr1.length = 0;
for (var i = 0; i < arr2.length; i++) {
arr1.push(arr2[i]);
}
// logs: [4,5,6] true
console.log(arr1, arr1===referenceToArr1);
// logs: [4,5,6]
console.log(referenceToArr1)
The downside here is that you need to clear arr1.length = 0
, iterate through each element of arr2
, and manually push them into arr1
.
Some questions to consider:
- Could a helper function make this process more efficient?
- Is there a concise vanilla JavaScript solution for this task (possibly a one-liner)?
- I use underscore.js but haven't found a method for this. Can underscore.js help in this situation?
Context:
I am working on an AngularJS app involving a service that contains an array holding data fetched from a server. This data is bound to a controller and displayed in a view. When the service data is updated (e.g., due to a refetch), I want the controller variables and the linked view to update automatically.
Check out the Plunker example here: http://plnkr.co/edit/8yYahwDO6pAuwl6lcpAS?p=preview
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, myService) {
$scope.name = 'World';
myService.fetchData().then(function(data) {
console.log(data)
$scope.data = data;
})
});
app.service('myService', function($timeout, $q) {
var arr;
var deferred;
var loadData = function() {
// Data comes from the server here
var serverData = [1,2,3];
arr = serverData;
deferred.resolve(arr);
// Simulate a data refetch
$timeout(function() {
var newServerData = [4,5,6];
// Reassigning won't work as the MainCtrl loses its reference
// arr = newServerData;
}, 1000);
$timeout(function() {
var newServerData = [7,8,9];
arr.length = 0;
[].push.apply(arr, newServerData);
}, 2000);
$timeout(function() {
var newServerData = [10,11,12];
[].splice.apply(arr, [0, arr.length].concat(newServerData));
}, 3000);
}
return {
fetchData: function() {
deferred = $q.defer();
loadData();
return deferred.promise;
}
}
})
View code:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7c1d121b09101d0e52160f3c4d524e5204">[email protected]</a>" src="https://code.angularjs.org/1.2.16/angular.js" data-semver="1.2.16"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<ul>
<li ng-repeat="d in data">{{d}}</li>
</ul>
3 refetches every second
</body>
</html>