Recently I posted my findings about private fields in JavaScript. So this is a continuation of the post and it talks about public fields in your JavaScript code. So here is a quick example of public properties in your code:
function User() { // Private property var name = ''; return { // Public property classVersion: '1.3', prevVersions: ['1.2.3', '1.2', '1'], setName: function(newName) { name = newName; }, getName: function() { return name; } }; } var user = new User(); user.classVersion; // 1.3 user.prevVersions; // ['1.2.3', '1.2', '1']
NOTE:
Define an object property name in your return statement and it will be accessible from outside. In other words - public field.
Public and private methods in JavaScript
I have been talking about public and private properties so far. I guess it is time for private and public methods. The idea behind is the same. To make a method public you need to define it in your return object and if you want to make it private you should declare it outside your return.
Basically:
function User() { // Private variable var name; // Private method var privateMethod = function(){ // Access to private fields name += " Changed"; }; return { // Public methods setName: function(newName) { name = newName; privateMethod(); }, getName: function() { return name; } }; } var user = new User(); user.setName("My Name"); user.getName(); // My Name Changed
As you can see, privateMethod
and name
are declared outside the return
object and thus they are made private. Variables declared inside the return object are public and accessible using dot notation.
Don't you realize how wrong your approach is? Fine, you have private and public methods. But you also have totally broken objects! The methods are created during instantiation time instead of class loading time. That's really really bad. If you create 1000 instances of your User class which has three methods then you have a total of 3000 methods in memory.
ReplyDeleteTry it out:
var user1 = new User();
var user2 = new User();
alert(user1.setName === user2.setName);
You see? The methods are not the same as it should be. If you use JavaScript as it was meant to be used (using prototypes) then it doesn't matter how many instances you create, you always have just the three methods in memory and the test above outputs "true".
You simply have to deal with the fact that JavaScript doesn't know the concept of private members. But please stop teaching others a totally wrong way to do object oriented programming in JavaScript!
The following syntax will work just as well. Basically, everything refered to with "this" is public, the rest is private.
ReplyDeletefunction User() {
// Private property
var name = '';
//Public members
this.classVersion: '1.3';
this.prevVersions: ['1.2.3', '1.2', '1'];
//Public methods
this.setName: function(newName) {
name = newName;
};
this.getName: function() {
return name;
};
};
var user = new User();
user.classVersion; // 1.3
user.prevVersions; // ['1.2.3', '1.2', '1']
@Klaus Reimer, yes, I can't agree more with you. I, myself, was arguing with one of my colleagues that JavaScript is not object-oriented programming language and that it was wrong to compare it to other languages on that basis.
ReplyDeleteLet's face it, you are not going to create 1000 User object instances in your web app. Event if you do still they are created on client's PC and we can be sure that it can handle not only 1000 objects.
Anyway, that's not my point. The point is that there are JavaScript interpreters like Google's V8 JavaScript Engine (http://code.google.com/p/v8/) and I think having private fields and methods would probably be nice.
This is my opinion and I am by no means propagating javascript as a OO language.
@Mohamed Attahri, Thanks for sharing...
Here's a bonus to the pattern of public properties:
ReplyDeletefunction User() {
function privFunc(){publicAPI.pubProp++;}
var publicAPI = {
pubFunc:function(){privFunc();},
pubProp:1
};
return publicAPI;
}
var u1 = User();
u1.pubFunc();
alert(u1.pubProp); // 2
u1.pubProp = 10; // change it, obj internally can see change!
u1.pubFunc();
alert(u1.pubProp); // 11
---------
Basically, by storing "publicAPI" as a reference to the object returned from the function/object instantiation, you can read/write the values from both outside the object and inside the object.
Check out Douglas Crockford:
ReplyDeletehttp://javascript.crockford.com/private.html
He explains very well how Javascript is OOP but the style is so different from what we are use to that we often don't recognize it as OOP.
What about something like this:
ReplyDeletefunction User() {
// Private property
var name = '';
//Public members
this.classVersion = '1.3';
this.prevVersions = ['1.2.3', '1.2', '1'];
//Public methods
this.prototype.setName = function(newName) {
name = newName;
};
this.prototype.getName = function() {
return name;
};
};
Would this actually work? If I am correct, you would have public functions that can access private properties, but the functions would not be copied 1000 times if you have 1000 instances because the functions are stored on the prototype. I think it is basically what Douglas Crockford does in his exploration of inheritance (look at the Sugar section):
http://javascript.crockford.com/inheritance.html
Not a big fan of this pattern, however Object literals work much better IMHO
ReplyDelete