Confusing example of Private V.S. Public method in book <Javascript Patterns>? - javascript

I've been reading Javascript Patterns by Stefanov recently. And I found this example confusing to me here:
Another case of using a convention to mimic functionality is the private members >con- vention. Although you can implement true privacy in JavaScript, sometimes >evelopers find it easier to just use an underscore prefix to denote a private >method or property. Consider the following example:
var person = {
getName: function () {
return this._getFirst() + ' ' + this._getLast(); },
_getFirst: function () {
// ... },
_getLast: function () {
// ... }
};
In this example getName() is meant to be a public method, part of the stable API,
whereas _getFirst() and _getLast() are meant to be private.
As I understand it, either a method is private or public is defined by the way it was written. For example, if we are talking about a constructor function, then, "this.getFirst() = function(){ ... } " would be a public method where as "var getFirst=function(){...}" would be private.
The example in the book is not a constructor function, tho. And I do believe one can't simply use an underscore to make a method public or private. How, then, shall we make private or public method in an object declared in the way as the example above?
Many thanks!

Javascript doesn't have really private variables / methods. The pattern (underscoring) is just coding convention. See MDN: Private properties. It reads
The above technique (underscoring) is simple and clearly expresses intent. However,
the use of an underscore prefix is just a coding convention and is not
enforced by the language: there is nothing to prevent a user from
directly accessing a property that is supposed to be private.
Meanwhile, you cannot use var getFirst=function(){...} inside Object literal {...} construction.

It looks like it's trying to say that getName(); is an accessor within the same class as the private data member functions.

Related

why typescript class expose all private members? [duplicate]

I'm looking at implementation of private members in TypeScript, and I find it a little confusing. Intellisense doesn't allow to access private member, but in pure JavaScript, it's all there. This makes me think that TS doesn't implement private members correctly.
Any thoughts?
class Test{
private member: any = "private member";
}
alert(new Test().member);
Just as with the type checking, the privacy of members are only enforced within the compiler.
A private property is implemented as a regular property, and code outside the class is not allowed to access it.
To make something truly private inside the class, it can't be a member of the class, it would be a local variable created inside a function scope inside the code that creates the object. That would mean that you can't access it like a member of the class, i.e. using the this keyword.
JavaScript does support private variables.
function MyClass() {
var myPrivateVar = 3;
this.doSomething = function() {
return myPrivateVar++;
}
}
In TypeScript this would be expressed like so:
class MyClass {
doSomething: () => number;
constructor() {
var myPrivateVar = 3;
this.doSomething = function () {
return myPrivateVar++;
}
}
}
EDIT
This approach should only be used SPARINGLY where it is absolutely needed. For example if you need to cache a password temporarily.
There are performance costs to using this pattern (irrelevant of Javascript or Typescript) and should only be used where absolutely necessary.
Since TypeScript 3.8 will be released you will be able to declare private field which can’t be accessed or even detected outside of the containing class.
class Person {
#name: string
constructor(name: string) {
this.#name = name;
}
greet() {
console.log(`Hello, my name is ${this.#name}!`);
}
}
let jeremy = new Person("Jeremy Bearimy");
jeremy.#name
// ~~~~~
// Property '#name' is not accessible outside class 'Person'
// because it has a private identifier.
Private fields starts with # character
Please note that these private fields will be something different than fields marked with private keyword
Ref. https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/
Once support for WeakMap is more widely available there is an interesting technique detailed in example #3 here.
It allows for private data AND avoids the performance costs of Jason Evans example by allowing the data to be accessible from prototype methods instead of only instance methods.
The linked MDN WeakMap page lists browser support at Chrome 36, Firefox 6.0, IE 11, Opera 23, and Safari 7.1.
let _counter = new WeakMap();
let _action = new WeakMap();
class Countdown {
constructor(counter, action) {
_counter.set(this, counter);
_action.set(this, action);
}
decrement() {
let counter = _counter.get(this);
if (counter < 1) return;
counter--;
_counter.set(this, counter);
if (counter === 0) {
_action.get(this)();
}
}
}
Thanks to Sean Feldman for the link to the official discussion on this issue - see his answer for the link.
I read the discussion he linked to, and here's a summary of the key points:
Suggestion: private properties in constructor
problems: can't access from prototype functions
Suggestion: private methods in constructor
problems: same as with properties, plus you lose the performance benefit of creating a function once per class in the prototype; instead you create a copy of the function for each instance
Suggestion: add boilerplate to abstract property access and enforce visibility
problems: major performance overhead; TypeScript is designed for large applications
Suggestion: TypeScript already wraps the constructor and prototype method definitions in a closure; put private methods and properties there
problems with putting private properties in that closure: they become static variables; there is not one per instance
problems with putting private methods in that closure: they do not have access to this without some sort of workaround
Suggestion: automatically mangle the private variable names
counter arguments: that's a naming convention, not a language construct. Mangle it yourself
Suggestion: Annotate private methods with #private so minifiers that recognize that annotation can effectively minify the method names
No significant counter arguments to this one
Overall counter-arguments to adding visibility support in emitted code:
the problem is that JavaScript itself doesn't have visibility modifiers - this isn't TypeScript's problem
there is already an established pattern in the JavaScript community: prefix private properties and methods with an underscore, which says "proceed at your own risk"
when TypeScript designers said that truly private properties and methods aren't "possible", they meant "not possible under our design constraints", specifically:
The emitted JS is idiomatic
Boilerplate is minimal
No additional overhead compared to normal JS OOP
I realize this is an older discussion but it might still be useful to share my solution to the problem of the supposedly private variables and methods in a TypeScript "leaking" out into the public interface of the compiled JavaScript class.
To me this issue is purely cosmetic, i.e. it's all about the visual clutter when an instance variable is viewed in DevTools. My fix is to group private declarations together inside another class that is then instantiated in the main class and assigned to a private (but still publicly visible in JS) variable with a name like __ (double underscore).
Example:
class Privates {
readonly DEFAULT_MULTIPLIER = 2;
foo: number;
bar: number;
someMethod = (multiplier: number = this.DEFAULT_MULTIPLIER) => {
return multiplier * (this.foo + this.bar);
}
private _class: MyClass;
constructor(_class: MyClass) {
this._class = _class;
}
}
export class MyClass {
private __: Privates = new Privates(this);
constructor(foo: number, bar: number, baz: number) {
// assign private property values...
this.__.foo = foo;
this.__.bar = bar;
// assign public property values...
this.baz = baz;
}
baz: number;
print = () => {
console.log(`foo=${this.__.foo}, bar=${this.__.bar}`);
console.log(`someMethod returns ${this.__.someMethod()}`);
}
}
let myClass = new MyClass(1, 2, 3);
When the myClass instance is viewed in DevTools, instead of seeing all its "private" members intermixed with truly public ones (which can get very visually messy in properly refactored real-life code) you see them neatly grouped inside the collapsed __ property:
In TypeScript Private functions are only accessible inside the class. Like
And it will show an error when you try to access a private member. Here is the example:
Note: It will be fine with javascript and both function are accessible
outside.
Here's reusable approach for adding proper private properties:
/**
* Implements proper private properties.
*/
export class Private<K extends object, V> {
private propMap = new WeakMap<K, V>();
get(obj: K): V {
return this.propMap.get(obj)!;
}
set(obj: K, val: V) {
this.propMap.set(obj, val);
}
}
Let's say you have class Client somewhere that needs two private properties:
prop1: string
prop2: number
Below is how you implement it:
// our private properties:
interface ClientPrivate {
prop1: string;
prop2: number;
}
// private properties for all Client instances:
const pp = new Private<Client, ClientPrivate>();
class Client {
constructor() {
pp.set(this, {
prop1: 'hello',
prop2: 123
});
}
someMethod() {
const privateProps = pp.get(this);
const prop1 = privateProps.prop1;
const prop2 = privateProps.prop2;
}
}
And if all you need is a single private property, then it gets even simpler, because you would not need to define any ClientPrivate in that case.
Worth noting, that for the most part, class Private just offers a nicely readable signature, whereas direct use of WeakMap does not.
In Summary - The type system will throw a warning message. But the private is a type system-specific feature, so it will go away at runtime.
Read an article I wrote about accessing TypeScript private variables here: https://szaranger.medium.com/stop-relying-on-private-to-hide-variables-in-typescript-3c45d25a58d0
Actually the answer to this question is rather simple.
You have this code:
class Test{
private member: any = "private member";
}
alert(new Test().member);
In that code, you are mixing two different languages. This part is TypeScript:
class Test{
private member: any = "private member";
}
and this part is JavaScript:
alert(new Test().member);
The private keyword in the Test class for member field is for TypeScript. Thus other classes within TypeScript cannot access the member field because the TypeScript compiler will not allow it. For example, if you tried this, it will not work:
class Test2 {
constructor() {
var test = new Test();
test.member = "Cannot do this";
}
}
It makes no difference whether you put private or public on the generated JavaScript. The generated JavaScript code will always be:
var Test = (function () {
function Test() {
this.member = "private member";
}
return Test1;
}());
Therefore, you are able to do this because JavaScript will allow this:
alert(new Test().member);
This is not a rule carved in stone and there may be cases that I am not aware of but if you are using TypeScript, then why worry about what you are allowed to do using JavaScript; the idea is that you are no longer writing JavaScript so what you can/cannot do in JavaScript should not be something to worry about anymore. To me this worry would be the same as writing C# code and then saying how come I am able to change the private field in CIL or assembly language. I am not sure if CIL allows it or not, but that is not the point. The point is you just don't go poking around in what you can do with CIL after you write code in C#.
There may be cases where you write code in TypeScript but the public may use the generated JavaScript, a plugin perhaps, and you don't want them to break things, well in that case you would worry about it. For those cases, you would write your TypeScript code to make the fields private even on the JavaScript side. Other answers have already covered on how to do that.

Is there a more elegant approach for private members of class instances?

I would like to set a design standard for class- as well as class-instance-creation. Combining lots of intel from multiple websites (e.g. from stackoverflow), there finally is a way to have a relative maximum of flexibility. My goal is exactly that in terms of having code-structures that behave similar to more defined classes of Java and the like.
Here is working codesnippet of what I have so far (including explanations):
var MyClass = function (prop1)
{
var _class = MyClass;
var _proto = _class.prototype;
// public member of constructed class-instance
this.prop1 = prop1;
// private static property as well as private member of class-instances
// (see getter below!)
var prop2 = this.prop1 * 10;
// need to use this. instead of _proto because the property prop2 of
// the class itself would be returned otherwise
this.getProp2 = function ()
{
return prop2;
}
// 1 function for all instances of the class
// reached by a fallback to the prototype
_proto.protoAlert = function ()
{
// must call this.getProp2() instead of using prop2 directly
// because it would use the private static member of the class
// itself instead the one of the class-instance
alert(this.prop1 + " " + this.getProp2());
}
};
var c1 = new MyClass(1);
c1.protoAlert();
var c2 = new MyClass(2);
c2.protoAlert();
c1.protoAlert();
This works well so far. However, there are some hurdles to take to not provoke errors and uncatched misbehavior of the script. The private property prop2 exists in both class and class-instances. It's a likely unintended double identity. Furthermore, the private property of class-instances are only properly reachable through setter- and getter-function. This is not the worst thing as it enforces a common way to access private variables. The downside is: Setters and getters have to be called with this. to actually reference to the prop2 of the class-instance then returning it. As for class inheritance - I didn't look into this topic with my current standard yet. Hopefully, it will work out as well.
Is there a more elegant solution or at least one that is less prone to possible errors?
Thank you in advance!
JavaScript does not really provide practical pattern for private properties. The pattern you're using does work only as long as you define all methods in constructor. You should keep in mind that this means every time you create the class, you create all the methods.
If you think about it, private variables are not serving any function in the program, they serve the programmer to keep in mind, that he should and what he should not be changing. As such, you can simply use some naming pattern. I've seen this a lot along other people's code:
function MyClass() {
// Private property
this._helloWord = "Hello word.";
}
// From outside, accessed as `helloWord`, without underscore
Object.defineProperty(MyClass.prototype, "helloWord", {
get: function() {console.log("helloWord getter");return this._helloWord;},
set: function(value) {console.log("helloWord setter");return this._helloWord = value;},
};
MyClass.prototype.alertProp = function() {
alert(this._helloWord);
}
// Accessing from the outside:
var instance = new MyClass();
alert(instance.helloWord); // will activate the getter function
Most people will instantly understand there is something special about _underscored variables. You can also make variable constant this way:
Object.defineProperty(MyClass.prototype, "helloWord", {
value: "Hello world",
writable: false // <----
};
Learn more about Object.defineProperty. You should also get to understand that the structure of Javascript is a little bit different than in OOP languages. If you try to push other languages' patterns on it, it will cause performance and structural problems.

Should prototype only be used for public methods in a class?

I have a js class that has no public methods. I'm using var's inside a constructor to create these methods and call them with methodName(). Should I use class.prototype.methodName instead and call them within the class with this.methodName()? What's the advantage of either approach? I know prototype methods get copied over to new instances, and thus is faster. But should they be used only for the API of the class?
JavaScript doesn't have private vairables, thus using a pattern that simulates them causes some overhead (more cpu and memory is needed to run your code). Code with privates can be harder to maintain.
The pattern that simulates private members can be split up in 2 different types:
Instance specific members
Prototype Members
Instance specific could be something like a person's religion and prototype member could be the doSomethingDangerous function. Before religion returns a value you may want to check if the requesting object has access to this private information. The function doSomethingDangerous should not be called directly because you can't be sure that when called from outside Person the right precautions have been taken before doing it.
Methods that can access "private" members are privileged methods. If they need to access instance specific members they need to be in the constructor body (that is where instance specific members are declared). If they need to access prototype specific members they need to be in the same body as where the "private" is declared.
Here is an example:
//constructor for Person
var Person = function(){//<=start body of constructor function
//to properly use prototype and not cause your code to consume
// more resources to simulate something that isn't supported
// in JavaScript "private" variable names usually start with _
// so other programmers know not to set, get or call this directly
this._normalPrivate;
var religion = undefined;//<=instance specific private
this.religion = function(){//<=privileged function
console.log(religion);//<=can access private instance here
}
};
Person.prototype=(function(){//<=start body of function returning object for prototype
//All person instances share this, it's not instance specific
var doSomethingDangerous=function(){//<=private prototype
// doing something dangerous, don't want this to be called directly
};
return {
doSomething:function(){//<=priviliged method, can access private prototype
//we cannot access religion because it's defined in a different
// function body
//make sure we can do something dangerous
doSomethingDangerous();
}
};
}());
Person.prototype.constructor=Person;
Person.prototype.anotherMethod=function(){
//not a privileged method, cannot access doSomethingDangerous or religion
};
var ben = new Person();
I never use this pattern though because private is only used to indicate to other programmers not to directly access these members. As in the following example you don't want a programmer (including yourself in the future) to do something like:
ben._doSomethingDangerous();
To indicate to other programmers (and future self) that doSomethingDangerous is private you can add an underscore in front of it:
Person.prototype._doSomethingDangerous=function(){...
More on prototype, inheritance, mix ins here https://stackoverflow.com/a/16063711/1641941

Javascript Modular Prototype Pattern

The problem with functional inheritance is that if you want to create many instances then it will be slow because the functions have to be declared every time.
The problem with prototypal inheritance is that there is no way to truly have private variables.
Is it possible to mix these two together and get the best of both worlds? Here is my attempt using both prototypes and the singleton pattern combined:
var Animal = (function () {
var secret = "My Secret";
var _Animal = function (type) {
this.type = type;
}
_Animal.prototype = {
some_property: 123,
getSecret: function () {
return secret;
}
};
return _Animal;
}());
var cat = new Animal("cat");
cat.some_property; // 123
cat.type; // "cat"
cat.getSecret(); // "My Secret"
Is there any drawbacks of using this pattern? Security? Efficiency? Is there a similar pattern out there that already exists?
Your pattern is totally fine.
There are a few things that you'd want to keep in mind, here.
Primarily, the functions and variables which are created in the outermost closure will behave like private static methods/members in other languages (except in how they're actually called, syntactically).
If you use the prototype paradigm, creating private-static methods/members is impossible, of course.
You could further create public-static members/methods by appending them to your inner constructor, before returning it to the outer scope:
var Class = (function () {
var private_static = function () {},
public_static = function () {},
Class = function () {
var private_method = function () { private_static(); };
this.method = function () { private_method(); };
};
Class.static = public_static;
return Class;
}());
Class.static(); // calls `public_static`
var instance = new Class();
instance.method();
// calls instance's `private_method()`, which in turn calls the shared `private_static();`
Keep in mind that if you're intending to use "static" functions this way, that they have absolutely no access to the internal state of an instance, and as such, if you do use them, you'll need to pass them anything they require, and you'll have to collect the return statement (or modify object properties/array elements from inside).
Also, from inside of any instance, given the code above, public_static and Class.static(); are both totally valid ways of calling the public function, because it's not actually a static, but simply a function within a closure, which also happens to have been added as a property of another object which is also within the instance's scope-chain.
As an added bonus:
Even if malicious code DID start attacking your public static methods (Class.static) in hopes of hijacking your internals, any changes to the Class.static property would not affect the enclosed public_static function, so by calling the internal version, your instances would still be hack-safe as far as keeping people out of the private stuff...
If another module was depending on an instance, and that instance's public methods had been tampered with, and the other module just trusted everything it was given... ...well, shame on that module's creator -- but at least your stuff is secure.
Hooray for replicating the functionality of other languages, using little more than closure.
Is it possible to mix functional and prototypical inheritance together and get the best of both worlds?
Yes. And you should do it. Instead of initializing that as {}, you'd use Object.create to inherit from some proto object where all the non-priviliged methods are placed. However, inheriting from such a "class" won't be simple, and you soon end up with code that looks more like the pseudo-classical approach - even if using a factory.
My attempt using both prototypes and the singleton pattern combined. Is there a similar pattern out there that already exists?
OK, but that's something different from the above? Actually, this is known as the "Revealing Prototype Pattern", a combination of the Module Pattern and the Prototype Pattern.
Any drawbacks of using this pattern?
No, it's fine. Only for your example it is a bit unnecessary, and since your secret is kind of a static variable it doesn't make much sense to me accessing it from an instance method. Shorter:
function Animal(type) {
this.type = type;
}
Animal.prototype.some_property = 123;
Animal.getSecret = function() {
return "My Secret";
};

What kind of a pattern/object is this in Javascript?

I see this pattern a lot (which I actually use) but I want an explanation as to how it works.
var mystuff = function() {
var blah = function() {
};
return {
setup: function() {
blah();
};
};
}();
Then usage is very OOP like:
mystuff.setup();
What that's doing is returning a public interface to your object. It looks like you are using the public setup() function to access the private blah() function. This is one method of emulating public and private member functions in Javascript objects.
Since mystuff is defined with that trailing () at the bottom, it's executed immediately when the parser reaches mystuff.setup(), and actually returns an anonymous object (your public interface) with the setup() method.
Others have explained how it works. This is just somemore background info on the topic.
It's called the "Module pattern" (coined by Douglas Crockford I believe, but blogged about earlier).
It gives you three main benefits:
A namespace (the value to the left of "function")
A private "space" to put stuff in (vars, functions, etc) that don't need or should not pollute the global namespace (this is the stuff before the return statement)
A public "space" to put stuff that you want accessible to users of your namespace (this is the return statement)
all in a fairly readable form.
This is simply an example of nested functions in JavaScript. Although the method of calling them may seem "OOP-like" on the surface, this style very much belongs to the functional paradigm.
In essence, however, there's nothing too fancy going on. JavaScript is known as a language in which "everything is a function", which is close enough to the truth. All it means is that any function declared belongs strictly to its parent scope.
It's from a functional programming approach to object oriented programming. Local variables in the outer (anonymous) function (the constructor) are accessible to any function defined within the constructor, but not elsewhere, making the local variables private. Where it differs from the purely functional approach is that the constructor returns an object literal rather than another function. The local variables are accessible by inner functions due to what's termed a closure.
It's use is to create private fields & methods, in the form of local variables.
but I want an explanation as to how it works.
Let's desect it piece by piece.
function() { .... } is a syntax for anonymous function.
function() { .... }() is defining and calling the anonymous function on the same line.
The return value of the function in your sample is an object defined using JSON notation (Javscript Object Notation)
{ setup : .... } is an object with one attribute: it's called setup, and it happens to be a function, in your case.
so, mystuff got the return value, which is an object with a property (function) called setup, and mystuff.setup() invokes this setup function.
Now, the interesting part is probably how setup just calls the blah function, defined inside that enclosing anonymous function.
I believe the technical term here is closure (see the section forming closures) (Also see the wikipedia definition)
Essentially the function becomes like a module of its own, with variables bound to it.
It's explained in crescentfresh's answer
First of all, please avoid this syntax:
var mystuff=function(){...}();
It is bad coding practice since it isn't completely cross-browser as a few browsers will error here.
Get used to putting parentheses around the function like so:\
var mystuff=(function(){...})();
Nextly, regarding the pattern. This pattern is more commonly known as simply "encapsulation" in JavaScript. Closures is another possibly but more specifically it is purely encapsulation in this case.
Encapsulation simply means you are making some members private. What is private in this case? Well the blah variable is private in this case. Please get into the habit of proceeding private members with an underscore to indiciate they are private. It is good coding practice to distinguish public methods from private methods with an underscore.
<script type="text/javascript">
var obj=(function(){
//private members
var _p={};//toss all private members into a single object.
_p.list=[];
_p.init=function(){
_p.list=[];
};
//public members. use "this" to reference object followed by the method.
//however obj._p.list won't be accessible to the global scope
return {
reset:function()
{
_p.init();
}
,addName:function(str)
{
_p.list.push(''+str);//limit to strings
}
,getNames:function()
{
return _p.list.slice(0);//return a clone
}
,alertNames:function()
{
alert(this.getNames().join(","));
}
,getPrivateObj:function()
{
return _p;
}
};
})();
obj.alertNames();
obj.addName("Nandan");
obj.addName("Ram");
obj.alertNames();
obj.reset();
obj.alertNames();
obj.addName("Vinoth");
obj.addName("Kevin");
obj.alertNames();
alert(typeof obj._p);//undefined
var privateObj=obj.getPrivateObj();
alert(typeof privateObj);
alert(privateObj.list.join("|"));
</script>

Categories

Resources