2

How do i make sku private but allow the getter access to it:

var Product = function (sku) {
    this.sku = sku;
};

Product.prototype.getSku = function() {
    return this.sku;
}

module.exports = {Product: Product};
Marty Wallace
  • 34,046
  • 53
  • 137
  • 200
  • I reopened the question because the OP didn't explicitly ask for solving this problem only via a prototype method and that's what the dup question was. – jfriend00 Feb 15 '15 at 18:29

4 Answers4

5

Since you refer to both "private" and "getter", it's not entirely clear what you want. If what you want is that the outside world can obtain the value, but cannot set the value directly, then there are a couple ways to do that:

Taking from Crockfords fairly old article on the topic of private member variables, you can create a method that has access to the private variable, but there is no other external access to the private variable (e.g. it cannot be set from the outside):

function Product(sku) {
    this.getSku = function() {
        return sku;
    }
}

var p = new Product(1234);
console.log(p.getSku());

The variable itself is private and cannot be set from the outside. But it's value can be retrieved with the getSku method.

The idea is that any variables that are local to the constructor function (including the arguments) are accessible only to the constructor itself and to any functions defined in the constructor, but not accessible to the outside world.

So, if you define some methods on the object in the constructor, then those methods and only those methods can access those local variables. As such, they are essentially private member variables because they are private and per-instance. It is the concept of Javascript closures that make this work.

This works with all browser versions.


Or, if you want sku to work like a read-only property where you can read it's value with property syntax rather than method syntax, you can define only a getter for it using Object.defineProperty() in the constructor like this:

function Product(sku) {
    Object.defineProperty(this, "sku", {
        get: function() { return sku;},
        writable: false,       // default value, doesn't have to be specified
        configurable: false,   // default value, doesn't have to be specified
        enumerable: false
    });
}

var p = new Product(1234);
console.log(p.sku);

P.S. Object.defineProperty() requires IE9 or higher.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 1
    You don't need to add `writable: false, configurable: false` and so on. They are `false` by default. – alexpods Feb 15 '15 at 18:16
  • 1
    @alexpods - Yes. That was done for the purposes of this answer to illustrate the features. I will make that clearer. – jfriend00 Feb 15 '15 at 18:18
  • Aside from browser support is there any preference over which method should be used? – Marty Wallace Feb 15 '15 at 18:20
  • @MartyWallace - the choice between these two is mostly whether you want to access it via `p.getSku()` or `p.sku`. That is your design choice. I would prefer `p.sku` myself, but your doc would need to make it clear that you can't set that property. – jfriend00 Feb 15 '15 at 18:21
  • @jfriend00 Ok, then. Upvote from me for well explained answer) – alexpods Feb 15 '15 at 18:23
2

Use Object.defineProperties or Object.defineProperty:

var Product = function (sku) {

    Object.defineProperty(this, 'sku', {
        get: function() { return sku }
    })
};

module.exports = {Product: Product};

For node.js you also can use __defineGetter__ (but this method was deprecated in ES spec):

var Product = function (sku) {

    this.__defineGetter__('sku', function() {
        return sku;
    });
};

module.exports = {Product: Product};
alexpods
  • 47,475
  • 10
  • 100
  • 94
0
var Foo = (function(){

  var a_ = 0;

  function ret(v) {
    if (v) a_ = v;
    return ret;
  }

  // getter and setter for a_
  ret.a = function(v) {
    if (v) a_ = v;
    return a_;
  };

  return ret;

})();

var foo = Foo();
console.log(foo.a());
foo.a(33);
console.log(foo.a());

var bar = Foo(100);
console.log(bar.a());
gongzhitaao
  • 6,566
  • 3
  • 36
  • 44
0

Use Object.defineProperties on prototype:

var Product = function (sku) {
  this._sku = sku;
};

Object.defineProperties(Product.prototype, {
  "sku": {
    get: function () { return this._sku; },
    set: function () { throw new Error("cannot set sku"); }
  }
});

module.exports = Product;
oaleynik
  • 655
  • 5
  • 19