2

I'm trying to make a object private, but not sure how to do that. As you can see the name variable is private, I can't edit it but when it comes to the object that I return, I can edit. I dont want that to be possible, though. I quite new to object-oriented and private methods in javascript, so could someone tell me what's right and wrong here. :) How can I solve this? Thanks!

var User = function() {

  var name = 'bob';
  this.getName = function() {
    return name;
  }

  var otherInfo = {
    age: 20,
    human: true,
  }
  this.getOther = function() {
    return otherInfo;
  }

}

var person = new User();

var name = person.getName();
name = 'jenny';
console.log(person.getName()); // bob

var other = person.getOther();
other.age = 'wtf?';
console.log(person.getOther()); // { age: 'wtf?', human: true }
  • If you don't want changes to the return value of `person.getOther()` to change the value of `otherInfo`, then you need to return a copy of it. – forgivenson Apr 28 '16 at 10:57
  • http://stackoverflow.com/questions/728360/most-elegant-way-to-clone-a-javascript-object – Jonathan Apr 28 '16 at 11:04

4 Answers4

1

Primitive values such as Strings are passed by value. This means when you assign a String to your variable, you are setting the actual value of the String to the variable.

Objects are passed by reference. This means when you assign an Object to your variable, you are simply making a reference to the Object, not it's actual value. If you had one Object and assigned it to 6 different variables, each variable would have a reference to the same underlying Object.

In your example, your getOther method is returning a reference to the otherInfo object. So when you set the age property to "wtf", you are setting it on the Object that your variable refers to.

duncanhall
  • 11,035
  • 5
  • 54
  • 86
0

It is happen, because in JS object passes by link - there are not coped from source object.

Just try copy object:

var User = function() {

  var name = 'bob';
  this.getName = function() {
    return name;
  }

  var otherInfo = {
    age: 20,
    human: true,
  }
  this.getOther = function() {
    return Object.assign({}, otherInfo);
  }

}

var person = new User();

var name = person.getName();
name = 'jenny';
console.log(person.getName()); // bob

var other = person.getOther();
other.age = 'wtf?';
console.log(person.getOther()); // { age: 20, human: true }
0

You also declare var name twice.

When you var person = new User(); a var name is declared within the scope of the User function.

When you var name = person.getName(); you are declaring a variable with the same name outside the scope of the User function.

So, when you name = 'Jenny'; the interpreter associates this string the name variable outside the scope of User.

In general, it is a bad idea to use such variables with common names (name, title, id, ...) as global variables. I would refer to the object attributes with this. and define setters as well as getters. You can also ignore the setters and refer to the User attributes with person., like this:

function User() {
  this.name = 'bob';
  this.getName = function() {
    return this.name;
  }

  this.otherInfo = {
    age: 20,
    human: true,
  }
  this.getOther = function() {
    return this.otherInfo;
  }

}

var person = new User();

console.log(person.getName()); // bob
person.name = 'jenny';
console.log(person.getName()); // jenny

console.log(person.getOther(); // { age: 20, human: true }
person.otherInfo.age = 'wtf?';
console.log(person.getOther()); // { age: 'wtf?', human: true }
Marc Compte
  • 4,579
  • 2
  • 16
  • 22
0

You don't have “private” things in object scope in Javascript. The only way to hide things from the outside is with a function scope, like you did with name (a local variable in the function User).

To return an object with the same content every time, you could make the object inside the function. Like this, for instance:

this.getOther = function() {
    var otherInfo = {
        age: 20,
        human: true,
    }
    return otherInfo;
}

Or just:

this.getOther = function() {
    return {
        age: 20,
        human: true,
    };
}

In both cases, you will be creating a new object with every call.

njlarsson
  • 2,128
  • 1
  • 18
  • 27