DawnPaladin
DawnPaladin

Reputation: 1533

Getters can set private variables

I think I've misunderstood something about OOP in JavaScript. As I understand it, the point of setting up a private variable with its own getter and setter functions is to protect it from accidental alteration elsewhere in the program. But I'm finding it very easy to accidentally change private variables using their getter functions, which means I must be doing something wrong.

function Phone(os) {
  this.os = os;
  var _phoneBook = []; // phoneBook is intended to be private
  this.newNumber = function(phoneNumber) { // set new number
    _phoneBook.push(phoneNumber);
  }
  this.listNumbers = function() { // get all numbers
    return _phoneBook;
  }
}

var andy = new Phone("Android");
andy.newNumber("555-123-4567");
console.log(andy.listNumbers()); // => ["555-123-4567"]
// You shouldn't be able to set a private property through a getter function, but you can.
var extendedPhoneBook = andy.listNumbers().push("123-456-7890"); 
console.log(andy.listNumbers()); // => ["555-123-4567", "123-456-7890"]

Upvotes: 2

Views: 416

Answers (2)

Cesar Alvarado
Cesar Alvarado

Reputation: 111

That Array is being passed as a reference, so when calling listNumbers() you are returning the Actual Array to the exterior. You can return copies of the Array with something like this:

function Phone(os) {
  this.os = os;
  var _phoneBook = []; // phoneBook is intended to be private
  this.newNumber = function(phoneNumber) { // set new number
    _phoneBook.push(phoneNumber);
  }
  this.listNumbers = function() { // get all numbers
    return _phoneBook.slice(0);
  }
}

Upvotes: 2

Mike Corcoran
Mike Corcoran

Reputation: 14565

you might consider changing function listNumbers to something like enumerateNumbers that takes a function that gets passed a string for each number in your list to hide the internal array, something like this:

function Phone(os) {
  this.os = os;
  var _phoneBook = []; // phoneBook is intended to be private
  this.newNumber = function(phoneNumber) { // set new number
    _phoneBook.push(phoneNumber);
  }
  this.enumerateNumbers = function(cb) { // get all numbers
    for (var idx in _phoneBook) {
      cb(_phoneBook[idx]);
    }
  }
}

var andy = new Phone("Android");
andy.newNumber("555-123-4567");

andy.enumerateNumbers(function(num) { console.log(num); })

Upvotes: 0

Related Questions