devonJS devonJS - 2 months ago 11x
Javascript Question

Angular Service - return private value versus assignment by reference to private value

Discussing with a coworker the difference between getting a return value of a private array versus an assignment to a variable that is a reference to the private array , but couldn't think of a good reason why the following would yield different results:


app.controller("MyController", ["MyService", function(MyService) {
var ctrl = this;
ctrl.arrayAssign = [];

ctrl.doSomething = function() {
// Empty out array, usually assigned at one point, code is omitted for example
ctrl.arrayAssign = []

// This does not work, ctrl.arrayAssign = []
ctrl.arrayAssign = MyService.serviceArray;

// This works, ctrl.arrayAssign correctly assigned to serviceArray in MyService
ctrl.arrayAssign = MyService.getServiceArray();


app.service("MyService", [function(){
var service = this;
var serviceArray = [];

service.serviceArray = serviceArray;

// This is called, either from controller above, or another controller
service.assignToServiceArray = function(arr) {
serviceArray = angular.copy(arr);

service.getServiceArray = function() {
return serviceArray;

return service;

Note: ctrl.doSomething() is called after service.assignToServiceArray()

What is a good explanation to why the two controller assignments above have different results as described?

I thought service.serviceArray would expose the private array serviceArray and just become a reference to the private array (service.serviceArray = serviceArray), so a new assignment to serviceArray (i.e. from service.assignToServiceArray), should allow service.serviceArray to reference the new array assignment which can be accessed directly by a controller.

service.getServiceArray() would also expose the private variable serviceArray, but directly, as in I'm not trying to access a variable that is just a reference to the array (i.e. service.serviceArray above).

Would trying to assign a reference to a private variable not be ideal in this case and just returning a private value be favored? I'm probably missing something really obvious...


service.serviceArray = serviceArray assigns a reference to [] array to serviceArray property, not a reference to serviceArray variable.

When a new value is assigned to serviceArray, it is assigned to this variable and nothing else.

A good thing about angular.copy is that it accepts two arguments and allows to keep the reference to the object:

If a destination is provided, all of its elements (for arrays) or properties (for objects) are deleted and then all elements/properties from the source are copied to it.

So it would work with:

angular.copy(arr, serviceArray);

The service in fact misuses OOP features that are provided by JS. service service accepts a constructor function. There's no problems like this if it behaves like normal object constructor:

app.service("MyService", [function(){
    this.serviceArray = [];

    service.assignToServiceArray = function(arr) {
        this.serviceArray = arr;

    service.getServiceArray = function() {
        return this.serviceArray;

    // not needed
    // return service;

If MyService.serviceArray is supposed to be used after its reassignment, it should be referred everywhere only by its getter and setter methods. The actual reason for getters and setters in OOP is that the value is being kept private and never accessed from the outside directly. E.g. in view:

{{ vm.MyService.getServiceArray()[0] }}