90 likes | 231 Views
JS Classes With Private Members. By Chris West. Is JavaScript Object-Oriented?. Contains objects Data Methods Doesn’t have classes Does have constructors Does have prototype functions Doesn’t provide information hiding??? No private members “per se” Can closures be used???.
E N D
JS Classes With Private Members By Chris West
Is JavaScript Object-Oriented? • Contains objects • Data • Methods • Doesn’t have classes • Does have constructors • Does have prototype functions • Doesn’t provide information hiding??? • No private members “per se” • Can closures be used???
Douglas Crockford’s Method // Person class – example of access to private data members via functions function Person(firstName, lastName) { // Define a `getName()` function for combining the private name variables. this.getName = function() { return firstName + " " + lastName; }; // Define a `setLastName()` function to update the private last name variable. this.setLastName = function(newLastName) { lastName = newLastName; return this; }; } // Sets age for object, but publicly Person.prototype.setAge = function(age) { this.age = age; }; // Getter for the public `age` property Person.prototype.getAge = function() { return this.age; };
Downfall of Crockford’s Method • All instances of the Person pseudo-class have unique private member accessor methods. var a = new Person("John", "Resig"), b = new Person("Douglas", "Crockford"); alert(a.getName == b.getName); // false alert(a.getAge == b.getAge); // true • Prototype functions don’t have direct access to the private members. Person.prototype.getFirstName = function() { return this.getName().replace(/.*? /g, ""); }; • No direct access to the private members. • If first name has a space in it, this will not work correctly.
Privileged Prototype Functions • Prototype functions are good — no unnecessary duplication • Prototype functions have access to any variables in their ancestral function scopes • Let’s use a closure to solve our dilemma
Privileged Prototype Functions (function(key) { // Define Person in global scope Person = function(firstName, lastName) { // Store private members in one object. varprivateVars = { firstName : firstName, lastName : lastName }; // Define a getter function that will only return private members // for privileged functions. this._ = function(aKey) { return aKey === key && privateVars; }; }; /* PROTOTYPE FUNCTIONS DEFINED ON NEXT SLIDE */ })({});
Privileged Prototype Functions (function(key) { /* ...CODE IN CLOSURE FROM PREVIOUS SLIDE... */ // Define a getter for the full name. Person.prototype.getName = function() { var _ = this._(key); return _.firstName + " " + _.lastName; }; // Define a setter for the last name. Person.prototype.setLastName = function(newLastName) { this._(key).lastName = newLastName; return this; }; // Define a getter for the first name. Person.prototype.getFirstName = function() { return this._(key).firstName; }; })({});
PROS & Cons • Pros • Create prototype functions that now have access to private variables. • Eliminate duplication of getters and setters for each instance. • Using a closure to prevent access from outside code. • Cons • A function call to access private members. • Still have one function that is being duplicated for each instance. • Overwriting the `_` (underscore) function will render the object useless. • If the closure code is changed, the private members can become public.
Final Notes • The pros outweigh the cons. • The `_` (underscore) function is really lightweight. • Developers rarely overwrite an object’s `_` (underscore) property. • Being able to change the code will always be a con of client-side JS code. • Currently in use • jPaq Color object • implementation of a JS Hashtable class • JavaScript is not necessarily object-oriented, but due to its unique capabilities, it doesn’t need to be.