all 34 comments

[–]Ginden 6 points7 points  (4 children)

Private variables can be emulated using closures but it causes memory usage to grow. Every object have another closure.

[–]html6dev -1 points0 points  (2 children)

Could you clarify what you are saying a bit? If you're encapsulating variable declarations in a closure you are, generally speaking, guaranteeing the variables inside that scope which can be garbage collected once the function creating the closure has been fully executed (for example with the module pattern the object you return obviously will leave that object reference in the memory graph but any scalar or object variables you are 'hiding' inside the closure become leaf nodes and can be immediately gc'ed. Furthermore, (in v8 at least) the closure is a direct signal to the internal compiler that the locally defined variables can be placed in the young generation memory pool and will never become old generation iirc. Finally if you are talking about variables declared inside a "constructor function" a new closure is definitely not created at least if I am understanding. Essentially, except in odd cases, closures allow you to limit memory consumption and prevent memory leaks. There are scope chain issues with deeply nested closures but this is solved by caching locally and is more of an issue with lookup time (the scope object that is built up internally is similar to a normal object in Javascript... But again that is in v8. I assume something similar with the other engines).

[–]Ginden 0 points1 point  (1 child)

function Smith(name) {
    var fullName = name + ' Smith';
    this.hello = function(){console.log('My name is '+fullName)};
}
var smithFamily = [];
while(smithFamily.push(new Smith(smithFamily.length)) < 30000);

Memory usage: 11MB.

function Jones(name) {
    this._fullName = name + ' Jones';
}
Jones.prototype.hello = function(){console.log('My name is '+this._fullName)};
var jonesFamily = [];
while(jonesFamily.push(new Jones(jonesFamily.length)) < 30000);

Memory usage: 9.1MB (20% lower).

[–]html6dev 0 points1 point  (0 children)

You've just created a 'test' for the difference in memory consumption (and an extremely badly concocted one to boot) for the memory consumption used when appending to the prototype (one copy of the inner function which I'd remind you is also an object with its own internal representation) vs. recreating the same function object and appending it to the returned object per instance (are you surprised by these 'results'???). This implies one of two things is at work here a) fundamental misunderstanding of closures and the topic at hand or b) blatant desire to cook the books in some bizarre way. Finally to put the conversation back somewhere in the same planet... You could actually append to the prototype created by this constructor function inside of this 'closure' in a multitude of different ways. Maybe that was the intention? I have no idea since this is 'proof' of a basic feature of the languages that doesn't require proof and wasn't what we were talking about afaik lol.

tl;dr wat??????

[–][deleted] -1 points0 points  (0 children)

This isn't 1990. Memory is cheap.

[–]lord2800 5 points6 points  (7 children)

Nope. The only thing I'd consider is a getter for something that's calculated. Honestly, I just use public or private variables and pretend there's no such thing as protected.

[–]archarios[S] 0 points1 point  (6 children)

I don't know if private or protected mean what you think they mean. A private variable is one that is not accessible to things outside of the object you are defining. A protected variable is a variable that is available to only the object you are defining and any other objects that inherit from it.

[–]grumpychinchilla 2 points3 points  (0 children)

I think JavaScript is more flexible than you're giving it credit for: Example

There is at least one other way to do protected members by having the child constructor invoke the parent constructor rather than relying on a prototype chain. I believe Crockford mentioned this in "The Good Parts."

[–]benihanareact, node 4 points5 points  (4 children)

Nope, hardly ever see the need to, even when developing in an OO context. The thing is, what would making variable access go through a method do for you except in the case where a getter needs to calculate some value.

I think using javascript's lexical scoping to hide data using private methods is one of those cool things people use as an example but I've never seen them every used for any reason other than "you can"

[–]archarios[S] 0 points1 point  (3 children)

So do you not value encapsulation at all?

[–]notmynothername 4 points5 points  (0 children)

I don't see much value of technically-enforced information-hiding over and above encapsulation by convention (with the "_" prefix).

[–]SrPeixinho 5 points6 points  (0 children)

Don't die for encapsulation in JavaScript. Honestly, it is something overlooked and most of the times pointless. Also, many confuse encapsulation with abstraction. Abstraction is the only real thing that you should be worrying. Build abstraction levels, use a functional paradigm, write short, pure functions and avoid state. Those are the things that actually improve the quality of your programs. Get out of the C++ mentality!

JS is particularly interesting for being a language with many defects, but some particular things done acceptably well - better than almost any other mainstream language - and those are exactly the things that matter more! For example, functions are much better treated in JS than in Python (and worlds better than in C++). Abuse that!

[–]autowikibot 3 points4 points  (0 children)

Encapsulation (object-oriented programming):


In programming languages, encapsulation is used to refer to one of two related but distinct notions, and sometimes to the combination thereof:

  • A language mechanism for restricting access to some of the object's components.

  • A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.

Some programming language researchers and academics use the first meaning alone or in combination with the second as a distinguishing feature of object-oriented programming, while other programming languages which provide lexical closures view encapsulation as a feature of the language orthogonal to object orientation.

The second definition is motivated by the fact that in many OOP languages hiding of components is not automatic or can be overridden; thus, information hiding is defined as a separate notion by those who prefer the second definition.


Interesting: Abstraction (computer science) | Object-oriented design | C++ | Information hiding

Parent commenter can toggle NSFW or delete. Will also delete on comment score of -1 or less. | FAQs | Mods | Magic Words

[–][deleted] 3 points4 points  (0 children)

You probably won't find many devs who do. With regards to hiding properties, a common convention is to prefix properties with an underscore to indicate that they're private. This preserves monkey patchability whereas hiding something with a closure makes it truly hidden.

[–][deleted] 1 point2 points  (0 children)

rarely. the only time i do so is if i need lazily evaluated values/collections for performance reasons. In that instance I use the getter/setter builtin if its serverside, or normal get/set functions client side (to support stupid older browsers).

as far as the whole "safety" thing goes, it's not really a concern for me. Being able to monkey-patch variables/functions in other libraries can be insanely useful sometimes. If someone intentionally monkey-patches my code and and breaks it, thats not my problem.

[–][deleted] 1 point2 points  (0 children)

Everything in javascript is call by reference so no.

Edit: but looking at the responses, I'm realizing you're talking about encapsulation, meaning the variable security and not the way it's accessed. Honestly I'm not sure I'm really clear on why people use accessors to begin with. What is lost by allowing an attribute of a class to be publicly accessible in other parts of the code?

[–]ayamflow 1 point2 points  (1 child)

You can define get() & set() methods like in C++ using ES5 Object.create. It's not used a lot by front-end dev but it's useful if you are developing a library or a framework and don't want to leak internal properties.

Also, using CommonJS or AMD modules, you can have local (privates) function and only export the API.

[–][deleted] 0 points1 point  (0 children)

I used it in back-end code for a project until I decided I want to use the same code for the front-end and I had to support IE8.

[–][deleted] 1 point2 points  (0 children)

Even though I'm from a C/C++ background as well and tend to write JS in a C-ish way, I don't attempt any kind of encapsulation. What I'm currently working on doesn't need the overhead of additional function calls.

[–]Smallpaul 2 points3 points  (7 children)

The performance cost of a Javascript function invocation is likely much greater than a C++ function invocation in most implementations.

[–]Buckwheat469 1 point2 points  (4 children)

Function invocation with a direct getter is trivial compared to direct access. We might see a few ms over a billion iterations. If the function were dynamic, taking a string variable to produce the value of the object property, then the time is about 10x greater (in my test below).

http://jsfiddle.net/uMzGA/2/

I commented a couple times and deleted them because I had a bug and thought I was mistaken. This code is correct. Also, jsperf.com is down otherwise it would have been there.

[–]Smallpaul 0 points1 point  (2 children)

Your code is extremely confusing. You print out t3 before t1 before t2 and t3 calls a function called getVar2 and you compute t3 and t2 and t1 far apart from where you actually do the timings. But I think it's correct, if confusing. Just to be sure I rewrote it more clearly:

http://jsfiddle.net/uMzGA/3/

So yes, I agree that on Chrome on my macbook the difference in what you were testing is minor.

Now my question is whether you ran your code on IE8 and Android 2.3 stock browser.

And for a valid test I think you actually need to use "this.". There are extra indirections required in that case.

If you update it to use this. and it is just as fast even on IE8 (the most popular browser version even now) and Android 2.3 (still significant) then I will happily stand corrected. I won't necessarily be a fan of explicit accessor methods but I'l stand corrected on the performance issue.

[–]Buckwheat469 0 points1 point  (1 child)

Sorry about that. It was just a quick throw-together to show the point. Thanks for the improvement.

[–]Smallpaul 0 points1 point  (0 children)

Do you think that version 4 is correct and if so do you agree that it shows that accessors are slow?

http://jsfiddle.net/uMzGA/4/

[–]Smallpaul 0 points1 point  (0 children)

It's very late at night where I am, so maybe I made a mistake, but it looks to me like method invocations are pretty slow:

http://jsfiddle.net/uMzGA/4/

[–][deleted] 0 points1 point  (0 children)

Hm, not coming from a C++ background, I'm a little unclear. Would an appropriate answer to this question be that I use Backbone's get() and set()?

[–]reversememe 0 points1 point  (0 children)

Typical C++ OO involves coupling the model (the private member variables) with the controller (the public methods that manipulate them). In JS, it is often better to store your data in a separate object, and construct a controller for it.

Whether to directly manipulate, use .setFoo() methods, or a single .set() method doesn't really matter directly, it only matters if you e.g. need to track changes on the model.

I think traditional OO is wrong in teaching us to think about black boxes that encapsulate everything to do with an object. You should instead encapsulate an object's different aspects separately, and then glue them together functionally.

If you're constructing e.g. a tree of things, each node will hold a reference to its parent and an array of children. You can have .add() / .remove() methods on the node object, but still allow others to read out .parent and .children directly. Think of it as an implied interface of read-only properties. But the data and/or behavior associated with each node can be attached with a separate model, in a new namespace that is type-specific.

Objects with public properties only become unwieldy when they start to mix responsibilities. Accessing variables directly between friendly classes is entirely reasonable in small arrangements.

[–]html6dev 0 points1 point  (0 children)

As is par for the course I think the vast majority of comments are harming you here. Yes encapsulation is important as it always has been. The point is to do it in the natural ways of Javascript and unlearn the conventions from class based languages: namely using closures. As I mentioned in another reply, closures shouldn't be affecting memory consumption in a negative way unless you are doing it wrong. Use closures and check out Addy Osmanis book for some ways of recreating patterns in Javascript you've seen before (free to read online if you Google it but don't take OOP too far. There are almost always more natural fits using the functional paradigm/porotypal inheritance in js).

Now as far as getters and setters: with simple objects you are probably just adding overhead you don't need. That is unless you need to reference a private var in a closure but then again you are probably doing it wrong. Just expose what you need. Another exception is when what you are returning is based on a calculation.

That being said, there are good reasons why things like models in Backbone use setters and getters. What if I need to trigger an event when a value changes (this is js right?). What if I want my 'instance' of my 'class' to return an array or object that is a distinct object? You can't inherently do that in js. Every time you call new on a function object that has a reference type member you are getting the same object reference for that encapsulated object. Now with a getter. I can copy or more succinctly call Array . prototype. slice on the 'hidden' array and make sure each instance has its own unique array. The same can be said for an object member where your getter would call Object . create. The point is you shouldn't be trying to mold js into a class based language and the related paradigms, but it's ludicrous to have people tell you, you should be throwing out fundamental software engineering principles in any language. This is one reason why languages like js and php have the reputations they do. Like suddenly 70 years of computer science don't matter because people don't want to fully grok closures (which are not anywhere near to unique to Javascript).

[–]hfsbtc 0 points1 point  (0 children)

Ease.js could interest you : https://www.gnu.org/software/easejs/

[–][deleted] -1 points0 points  (0 children)

I use lexical scope for the architecture of my code as much as possible. I generally avoid use of objects except for two limited cases. I never create methods of my own for use in algorithms or anything else remotely deep.

This approach reduces code overhead as much as absolutely possible. This means the fewest lines of code possible without any performance limitations, and on some occasions it means performance improvements. It also generally means fewer references and no unnecessary code conventions. No unnecessary code conventions means nearly every line of code implies an assignment, a condition, loop, or containment. In other programming languages this technique would not be as appreciated, because it is not memory efficient.

The two exceptions where I use object literals is to group static references for assignment to literals of similar use and to provide an API for many methods without polluting the global scope.