0

When define a class I want to define a class level property, which is shared by all instance objects, how should I defined it?
I can think of 2 approach:

  • Define on constructor

    After define constructor function, define property on constructor itself,
    format to access:
    constructor_name.propName

  • Define on prototype

    After define constructor function, define property on constructor's prototype,
    this might be hidden by instance property,
    format to access:
    obj.propName

So, which approach is proper? Or there are other solutions?

Edit: I want to know the case When property is string/number, not a function.

Eric
  • 22,183
  • 20
  • 145
  • 196
  • 1
    Possible duplicate of [Static variables in JavaScript](http://stackoverflow.com/questions/1535631/static-variables-in-javascript) –  Jul 08 '14 at 05:00
  • @JonathanLonowski yeah, that's why I mention call it by the constructor itself in that case, not by instance, – Eric Jul 08 '14 at 05:21
  • 1
    Neither is really more proper than the other in general. It depends on the individual use case and whether inheritance, including overrides, makes sense for it (prototype) or not (constructor) -- "*this might be hidden by instance property*" as you mentioned. – Jonathan Lonowski Jul 08 '14 at 05:37
  • @JonathanLonowski Ok, I will try to figure out in practice, I was wondering how extjs implement their complex oo mechanism... – Eric Jul 08 '14 at 05:42
  • 1
    Following answer may be of help. Has a very detailed explanation for people starting with JavaScript oop: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Jul 08 '14 at 06:06
  • @HMR Yeah, that's a great one. – Eric Jul 08 '14 at 07:01

2 Answers2

1

Define on prototype is proper.

Example:

function Foo() {
  this.name = 'Jone';
  this.func1 = function() {
    console.log('func1 print :' + this.name);
  }
}

Foo.prototype.func2 = function() {
  console.log('func2 print :' + this.name);
};

Foo.func3 = function() {
  console.log('func3 print :' + this.name);
}

var f = new Foo();
f.func1();  // func1 print :Jone
f.func2();  // func2 print :Jone
f.func3();  // error, instace f cannot call func3.

func1 is defined in constructor, and instance can call it.

func2 is defined in prototype, and instance can call it.

the difference between func1 and func2 is all instances of Foo will share func2 while each instance of Foo has a separate func1.

func3 cannot called by instance of Foo bcz func3 is property of Foo not property of instance of Foo.

isayme
  • 309
  • 2
  • 11
  • This is true when property is a function, but it seems a little different when property is a string/number, not a function, can you help to suggest on that too. – Eric Jul 08 '14 at 05:17
  • all instances will share properties(including functions and other types) defined in `prototype`, and if any property redefined in `constructor`, the new one will be priorer when accessing the property. – isayme Jul 09 '14 at 00:38
  • property on prototype is readonly, instance can't change it directly, so it's not proper. – Eric Jul 09 '14 at 02:47
  • In fact, property on prototype is not readonly. You can check the result in [Demo](http://jsfiddle.net/tddAm/). – isayme Jul 09 '14 at 04:24
  • The primary type age on prototype didn't change, instead it create a new instance property on p1, that's why p2's age is still 0 in your output. But the object type name, if you change the name property directly, it will be the same as age. But when you access property of property this is different, because it's not change the property directly, to the instance it's just reading operation. – Eric Jul 09 '14 at 07:53
  • Anyhow, thank you, you have raised some quite fallible concepts. – Eric Jul 09 '14 at 07:57
0

After checking a while, I try to give an answer myself.

Define on constructor:

good part: it won't be override by instance property which has the same name.
bad part: it can't be access via instance directly, due to not in the prototype chain,but access via constructor itself.

Define on prototype:

good part: it could be access via instance directly.
bad part: it might be hidden when instance define a property with the same name, and its readonly to instance, because when instance try to modify it, it actually create a new instance property instead of modify the one from prototype.

So, maybe it's more proper to define property that is not a function on constructor itself.
And, because of that decision, to keep sync, the class level property which is function, had better be defined on constructor itself too.

Tip: the method define on prototype (metioned by @isayme), should be viewed as instance method, but not class-level method, even though they are defined on prototype, because usually they will read/write instance property.

Eric
  • 22,183
  • 20
  • 145
  • 196