How can I get better at OOP? [closed] - javascript

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
This might come as a strange question to many of you, and I don't actually know if it is correct to say OOP in this context, because OOP (object-oriented programming) is usually associated with programming languages like C++ and Java, and not lightweight programming languages, or scripting languages. My question, however, is in the category of JavaScript, which is also object oriented. I do know about objects, properties, methods, prototypes and constructors, I just can't seem to get into my mind when to use objects.
When I am writing my web-applications, I, for some reason, never use objects. This annoys me, because when I read about objects in a variety of books and online articles, objects make everything so much simpler and, just to put it out there, I HATE repeating myself, and this is why I wish I knew when to use objects.
I really want to become better at using objects and when to use objects.
Can you please mention a few situations objects would be good? It would be really nice to have written down something you know you can go back and look at when you get confused about when to use these darn objects :)
I would love simple answers explaining why and when objects are to prefer.
I would also like if you could tell me if I am to use objects when I am in some special situations generally suitable for objects i.e. every time you want to _________ then you use an object...
I really hope you understand my question and you will consider that I'm somewhat new to this site and new to JavaScript
Thanks!

You probably use objects without even realizing it.
If you're writing Javascript that interacts with the DOM, you're using objects.
If you're using any of the Javascript frameworks out there (jQuery, MooTools, etc.), you're using objects.
Using objects will be useful when you need to encapsulate some commonly used code so that it can be easily re-used (within a single application or across multiple applications like jQuery plugins...which are objects in and of themselves).
And to answer the question in the title of your post...the only way to really get better at OOP is to practice! Reading and studying the subject can only get you so far.

First, you don't need to use objects to avoid repeating yourself. If you need to do the same thing at two points in your code, you can write a plain vanilla non-OOP function to do that and call it twice.
To summarize the advantages of OOP without writing a book here, OOP basically does three things for you:
Group related data together. Non-OOP programs often have a whole bunch of variables floating around in the main program that are only loosely related. With OOP, you put related variables into an object.
Associate functions with data. By putting functions in an object with the data they operate on (purists will say they are then "members" rather than "functions"), you make it clear to the reader that these go together.
Combining #1 and #2 lets you hide implementation details from other objects. You create the "public interface" for a class, the set of functions that other objects should call and that represent the logical things that this class does, and then any other functions you need can be hidden. (More explicitly in some languages than in others, but that's not the point here.)
Classes can inherit and mutate. If you have two similar classes A and B that should be mostly the same but with some minor differences, you can make a superclass C with all the common stuff and then A and B inherit from that and each adds in its own unique stuff. This is what is usually advertised as the power of OOP. Frankly, yes, it's way cool, and in some situations can be very handy, but I only use its true power occasionally, and I suspect the same is true of most programmers. (OOP enthusiasts feel free to jump in with how and why you use inheritance all the time.)
When to OOP it? Any time you have several pieces of data that logically go together, it makes sense to create a class to hold them. Like X and Y coordinates; or customer name, address, and zip code; or phaser range and phaser power consumption; or whatever.
Any time you have functions that logically operate on this related data, put them in the the class with the data. Like "capitalize customer name", "compute distance of this point from the origin", etc.
How and when to use inheritance is more complicated. I'll leave that for another time.

The first thing to remember, is that a lot of simple Javascript code really doesn't need to define objects (using them is inevitable, as all the stuff the DOM gives you are objects). Don't panic too much.
One of the good things about Javascript is that it supports a lot of different styles; OOP, imperative and functional.
One of the bad things about using Javascript is that because it supports a lot of different styles, it's hard to learn another style, at least until you are forced to an "a-ha" moment by something else.
Spending time in languages that are more inclined to force you into OOP (even when some would argue they shouldn't) is helpful here. C# and Java force one along OOP lines, though C++ does not (with the same strength and weakness here as with Javascript).
Try to think about the "things" in your program. Some of these things will already be modelled by objects (those the DOM gives you). Some really will just be numbers and strings and not worth composing beyond that (though learning how to add functionality to those types through prototype is a good idea too). Some will be "things" more complicated than a simple type and naturally suited to modelling as an object.
Do also look at functional programming in Javascript (e.g. passing a function as a parameter to another function is about the simplest example), as the interaction between this and OOP is one of the strongest elements in Javascript, and essential in defining methods on objects given the prototype-based OOP model it has.

My personal experience with OOP in JavaScript is a positive one, once I figured out to get it to do what I wanted of course, I usually use it in combination with jQuery so the resulting code can seem a bit.... odd.
function BlogPost(id,title,content)
{
this.id = id;
this.title = title;
this.content = content;
function display()
{
var post = $('<div class="blogpost"></div>');
$(post).append('<h2>' + this.title + '</h2>');
$(post).append('<p>' + this.content + '</p>');
var deleteButton = $('<span class="deletePost">delete</span>')
$(post).append(deleteButton);
$(deleteButton).click(this.delete)
$('#postcontainer').append(post);
}
function delete()
{
$.post('some/xhr/handeler',{id:this.id});
}
}
This is a quick (untested) class that can be used to dynamically add blogposts to a div with id postcontainer' and handles clicks on a delete button.

Think about how you can use objects to organize and simplify your application. I have found two metaphors useful:
A mechanical watch is made up of a number of gears, each of which serves a single purpose in the overall operation of the machine. If you think of your application as a watch, then objects are its gears.
A workgroup is made up of a number of people, each of whom performs a specific job. The people communicate with each other in performing their jobs, and the jobs fall along two lines--those that perform tasks (workers), and those that organize and direct the work of other people (managers).
You can use these metaphors to organize the work your application does. Start by dividing the app into functional layers; UI, business layer, and persistence, for example. Take each of your use cases, and distribute the work it does among these layers. That should give you a starting point for the classes you will need.
Make each class as self-contained a possible. you want to seal it off when it is done, like a .NET control. Classes should communicate with each other only through their interfaces, which are made up of properties and methods. These interfaces should have the smallest footprint (fewest public properties and methods) you can come up with. The idea is to isolate the side effects of a change to any class to that class alone.
If you do these things, you will be ahead of 80% of all programmers. You will find it much easier to develop and maintain even large applications, because you will be able to break complex problems down to simple components.

Javascript is just a terrible language to learn OOP in. I would recommend learning OOP in another language (like Java or C++) and then learn Object Oriented syntax in Javascript. At that moment you have all the ingredients.
That's when you can decide whether or not you want to be using an object for a task in Javascript or if it is enough to use just functions.
Personally, I mostly write non-object javascript and leave objects for when a task feels object oriented to me. For example, I used an object oriented design for a drag and drop script, in which you simply made a DragNDrop object with the correct parameters and the items in your page would be dragable from that moment on, or when I wanted to simplify some javascript xml handling functions, I wrote an object that wrapped the normal xml objects.

Justin Niessner said it and I can only add to his answer...
In addition to practice, I find reading other people's code very instructive. You need to be cautious because not all code is exemplary (to say the least) but developing critical skills is part of getting better.

In my opinion I think it's better to think about OOP in the context of a particular domain or business problem. For example, JavaScript uses objects to model browser behavior and attributes, e.g., Window, Frame, History...
A domain model of a business problem will contain objects that will be reflected in the programming code written OOP. For example, a university student application will have objects for students, professors, courses, curriculums, rooms and so on. Consequently, begin with your business problem and model the domain. Your OOP code should have objects modeled from your domain.
Source:http://csci.csusb.edu/dick/samples/uml0.html

You might be interested in design patterns (Book, Wikipedia), which tell you, how to solve common problems using OOP.
Many classical design patterns may not be so relevant for JavaScript, since in JavaScript there are other non OOP elements (e.g. functions), which can solve some problems even more elegant.
Some simple design patterns I can recommend to start with:
Abstract factory: Defer the instantiation of objects. In JavaScript in most cases a function will do the job.
Decorator: Transparently add functionality to an object at runtime. Can also be nested. Usage example: Logging
Composite: Treat a tree/graph of object like a single object.

I think that using classes in general and OOP principles, makes your code neater, more readable and makes you more productive .

Recently I worked on a web application that would require heavy client side Javascript.
Coming from C#/Java background I realized that Javascript would require a change of thinking, however I still wanted to apply good OO principles if possible, in particular to control the likely complexity of the application.
After a bit of searching I found a great book called Object Oriented Javascript by Stoyan Stefanov. It truly opened my eyes to power of this often called "toy language". Some sections on functional programming concepts, variable scoping and closures may even be a bit more advanced than you want.
However reading and applying many of these concepts from this book (closures, anonymous functions etc) in Javascript, has actually even helped me back in C# land where these concepts are only now becoming more mainstream.
Given your stated situation and goal I can highly recommend this book as one of the best ways to learn about doing OO in Javascript.

Javascript is much, much less object oriented than C# or Java; don't worry if your Javascript doesn't look object oriented.

Related

Use single line functions or repeat code

I was writing a Javascript code in which I needed to show and hide some sections of a web. I ended up with functions like these:
function hideBreakPanel() {
$('section#break-panel').addClass('hide');
}
function hideTimerPanel() {
$('section#timer-panel').addClass('hide');
}
function showBreakPanel() {
resetInputValues();
$('section#break-panel').removeClass('hide');
}
function showTimerPanel() {
resetInputValues();
$('section#timer-panel').removeClass('hide');
}
My question is related with code quality and refactoring. When is better to have simple functions like these or invoke a Javascript/jQuery function directly? I suppose that the last approach have a better performance, but in this case performance is not a problem as it is a really simple site.
I think you're fine with having functions like these, after all hideBreakPanel might later involve something more than applying a class to an element. The only thing I'd point out is to try to minimize the amount of repeated code in those functions. Don't worry about the fact that you're adding a function call overhead, unless you're doing this in a performance-critical scenario, the runtime interpreter couldn't care less.
One way you could arrange the functions to avoid repeating yourself:
function hidePanel(name) {
$('section#' + name + '-panel').addClass('hide');
}
function showPanel(name) {
resetInputValues();
$('section#' + name + '-panel').removeClass('hide');
}
If you absolutely must have a shorthand, you can then do:
function hideBreakPanel() {
hidePanel("break");
}
Or even
var hideBreakPanel = hidePanel.bind(hidePanel, "break");
This way you encapsulate common functionality in a function, and you won't have to update all your hide functions to ammend the way hiding is done.
My question is related with code quality and refactoring. When is
better to have simple functions like these or invoke a
Javascript/jQuery function directly? I suppose that the last approach
have a better performance, but in this case performance is not a
problem as it is a really simple site.
Just from a general standpoint, you can get into a bit of trouble later if you have a lot of one-liner functions and multiple lines of code crammed into one and things like that if the goal is merely syntactical sugar and a very personal definition of clarity (this can be quite transient and change like fashion trends).
It's because the quality that gives code longevity is often, above all, familiarity and, to a lesser extent, centralization (less branches of code to jump through). Being able to recognize and not absolutely loathe code you wrote years later (not finding it bizarre/alien, e.g.) often favors those qualities that reduce the number of concepts in the system, and flow down towards very idiomatic use of languages and libraries. There are human metrics here beyond formal SE metrics like just being motivated to keep maintaining the same code.
But it's a balancing act. If the motivation to seek these shorter and sweeter function calls has more to do with concepts beyond syntax like having a central place to modify and extend and instrument the behavior, to improve safety in otherwise error-prone code, etc., then even a bunch of one-liner functions could start to become of great aid in the future. The key in that case to keep the familiarity is to make sure you (and your team if applicable) have plenty of reuse for such functions, and incorporate it into the daily practices and standards.
Idiomatic code tends to be quite safe here because we tend to be saturated by examples of it, keeping it familiar. Any time you start going deep on the end of establishing proprietary interfaces, we risk losing that quality. Yet proprietary interfaces are definitely needed, so the key is to make them count.
Another kind of esoteric view is that functions that depend on each other tend to age together. An image processing function that just operates on very simple types provided by a language tends to age well. We can find, for example, C functions of this sort that are still relevant and easily-applicable today that date back all the way to the 80s. Such code stays familiar. If it depends on a very exotic pixel and color library and math routines outside of the norm, then it tends to age a lot more quickly (loses the familiarity/applicability), because that image processing routine now ages with everything it depends on. So again, always with an eye towards tightrope-balancing and trade-offs, it can sometimes be useful to avoid the temptation to venture too far outside the norms, and avoid coupling your code to too many exotic interfaces (especially ones that serve little more than sugar). Sometimes the slightly-more verbose form of code that favors reducing the number of concepts and more directly uses what is already available in the system can be preferable.
Yet, as is often the case, it depends. But these might be some less frequently-mentioned qualities to keep in mind when making all of your decisions.
If resetInputValues() method returns undefined (meaning returns nothing e.g) or any falsy value, you could refactorize it to:
function togglePanel(type, toHide) {
$('section#' + type + '-panel').toggleClass('hide', toHide || resetInputValues());
}
Use e.g togglePanel('break'); for showBreakPanel() and togglePanel('break', true) for hideBreakPanel().

how does prototype differ from oop [duplicate]

In JavaScript, every object is at the same time an instance and a class. To do inheritance, you can use any object instance as a prototype.
In Python, C++, etc.. there are classes, and instances, as separate concepts. In order to do inheritance, you have to use the base class to create a new class, which can then be used to produce derived instances.
Why did JavaScript go in this direction (prototype-based object orientation)? what are the advantages (and disadvantages) of prototype-based OO with respect to traditional, class-based OO?
There are about a hundred terminology issues here, mostly built around someone (not you) trying to make their idea sound like The Best.
All object oriented languages need to be able to deal with several concepts:
encapsulation of data along with associated operations on the data, variously known as data members and member functions, or as data and methods, among other things.
inheritance, the ability to say that these objects are just like that other set of objects EXCEPT for these changes
polymorphism ("many shapes") in which an object decides for itself what methods are to be run, so that you can depend on the language to route your requests correctly.
Now, as far as comparison:
First thing is the whole "class" vs "prototype" question. The idea originally began in Simula, where with a class-based method each class represented a set of objects that shared the same state space (read "possible values") and the same operations, thereby forming an equivalence class. If you look back at Smalltalk, since you can open a class and add methods, this is effectively the same as what you can do in Javascript.
Later OO languages wanted to be able to use static type checking, so we got the notion of a fixed class set at compile time. In the open-class version, you had more flexibility; in the newer version, you had the ability to check some kinds of correctness at the compiler that would otherwise have required testing.
In a "class-based" language, that copying happens at compile time. In a prototype language, the operations are stored in the prototype data structure, which is copied and modified at run time. Abstractly, though, a class is still the equivalence class of all objects that share the same state space and methods. When you add a method to the prototype, you're effectively making an element of a new equivalence class.
Now, why do that? primarily because it makes for a simple, logical, elegant mechanism at run time. now, to create a new object, or to create a new class, you simply have to perform a deep copy, copying all the data and the prototype data structure. You get inheritance and polymorphism more or less for free then: method lookup always consists of asking a dictionary for a method implementation by name.
The reason that ended up in Javascript/ECMA script is basically that when we were getting started with this 10 years ago, we were dealing with much less powerful computers and much less sophisticated browsers. Choosing the prototype-based method meant the interpreter could be very simple while preserving the desirable properties of object orientation.
A comparison, which is slightly biased towards the prototypes based approach, can be found in the paper Self: The Power of Simplicity. The paper makes the following arguments in favor of prototypes:
Creation by copying. Creating new objects from prototypes is accomplished by a simple operation, copying, with a simple biological
metaphor, cloning. Creating new objects from classes is accomplished
by instantiation, which includes the interpretation of format
information in a class. Instantiation is similar to building a house
from a plan. Copying appeals to us as a simpler metaphor than
instantiation.
Examples of preexisting modules. Prototypes are more concrete than classes because they are examples of objects rather than descriptions
of format and initialization. These examples may help users to reuse
modules by making them easier to understand. A prototype-based system
allows the user to examine a typical representative rather than
requiring him to make sense out of its description.
Support for one-of-a-kind objects. Self provides a framework that can easily include one-of-a-kind objects with their own behavior.
Since each object has named slots, and slots can hold state or
behavior, any object can have unique slots or behavior. Class-based
systems are designed for situations where there are many objects with
the same behavior. There is no linguistic support for an object to
possess its own unique behavior, and it is awkward to create a class that is guaranteed to have only one
instance [think singleton
pattern]. Self suffers from neither of these disadvantages. Any object
can be customized with its own behavior. A unique object can hold the
unique behavior, and a separate "instance" is not needed.
Elimination of meta-regress. No object in a class-based system can be self-sufficient; another object (its class) is needed to express
its structure and behavior. This leads to a conceptually infinite
meta-regress: a point is an instance of class Point, which is an
instance of metaclass Point, which is an instance of metametaclass
Point, ad infinitum. On the other hand, in prototype-based systems
an object can include its own behavior; no other object is needed to
breathe life into it. Prototypes eliminate meta-regress.
Self is probably the first language to implement prototypes (it also pioneered other interesting technologies like JIT, which later made its way into the JVM), so reading the other Self papers should also be instructive.
You should check out a great book on JavaScript by Douglas Crockford. It provides a very good explanation of some of the design decisions taken by JavaScript creators.
One of the important design aspects of JavaScript is its prototypal inheritance system. Objects are first class citizens in JavaScript, so much that regular functions are also implemented as objects ('Function' object to be precise). In my opinion, when it was originally designed to run inside a browser, it was meant to be used to create lots of singleton objects. In browser DOM, you find that window, document etc all singleton objects. Also, JavaScript is loosely typed dynamic language (as opposed to say Python which is strongly typed, dynamic language), as a result, a concept of object extension was implemented through the use of 'prototype' property.
So I think there are some pros for prototype-based OO as implemented in JavaScript:
Suitable in loosely typed environments, no need to define explicit types.
Makes it incredibly easy to implement singleton pattern (compare JavaScript and Java in this regard, and you'll know what I am talking about).
Provides ways of applying a method of an object in the context of a different object, adding and replacing methods dynamically from an object etc. (things which are not possible in a strongly typed languages).
Here are some of the cons of prototypal OO:
No easy way of implementing private variables. Its possible to implement private vars using Crockford's wizardry using closures, but its definitely not as trivial as using private variables in say Java or C#.
I don't know how to implement multiple inheritances (for what its worth) in JavaScript yet.
The difference between mainstream OOP class-based languages such as c# or java and prototype bases languages such as javascript is the ability to modify object types at runtime whilst in c# or java they gave up this ability in favor of static type checking by making classes fixed at compile time. JS has always been closer to the first original design of OOP of alan Kay and languages such as Smalltalk or simula.
this is achieved by making the blueprint itself an instance, types in prototype-based are actual instances that can be accessed and modified at runtime, in Javascript this is really easy using the prototype object, since every object type has this object.
example: type funcName.prototype.myNewMethod= function{ console.log("hello world")}

Working with many Javascript functions

I'm currently working with a personal library that's accumulated quite a number of "helper" functions, which are used throughout my architecture for various purposes. Back when there were only a few of them, I kept them in a single file and object so I could access them like so:
tools.parseSomething(obj);
This has been terribly handy, and keeps the code still somewhat organised and readable. The problem is that the file (and object) containing these methods is growing to an enormous size, and needs a cleanup. I was considering creating separate files for "categories" of functions and placing them in those, so they'd be accessed like:
tools.env.getEnvironmentInfo();
My concern with this approach is not the readability so much, but the performance of the look-up. From what I've read recently, object look-ups are no longer the major bottle-neck they used to be, but I still want my library to be as efficient as possible (readability second).
I also considered having the separate files, but add all of the functions to the parent object so they're still accessible in the original way, but stored separately. The object containing the functions is "static" and exists as a single instance.
My question is, with regards to what I've explained, what would be the most efficient method of storing and using a large amount of helper functions? By efficiency I mean performance, which is the sole area of concern for me at the moment.
I'd agree that premature optimization is going on here, however that wasn't your question.
I'd assert that instead of thinking in terms of loosely related scriptlets that 'do kind of related things', I'd suggest an richer object model that can be stateful and perhaps expose the behaviors you need while hiding some optimizations you feel are necessary like caching lookups, etc.
So instead of getEnvironmentInfo, why not have an Environment instance that has, for example, already fetched some parameters and stored internally so subsequent calls are made faster. From there you can create new environments or whatever other behaviors suit you.
This is just good programming practice in whatever language.

I want to stop using OOP in javascript and use delegation instead

After dabbling with javascript for a while, I became progressively convinced that OOP is not the right way to go, or at least, not extensively. Having two or three levels of inheritance is ok, but working full OOP like one would do in Java seems just not fitting.
The language supports compositing and delegation natively. I want to use just that. However, I am having trouble replicating certain benefits from OOP.
Namely:
How would I check if an object implements a certain behavior? I have thought of the following methods
Check if the object has a particular method. But this would mean standardizing method names and if the project is big, it can quickly become cumbersome, and lead to the java problem (object.hasMethod('emailRegexValidatorSimpleSuperLongNotConflictingMethodName')...It would just move the problem of OOP, not fix it. Furthermore, I could not find info on the performance of looking up if methods exist
Store each composited object in an array and check if the object contains the compositor. Something like: object.hasComposite(compositorClass)...But that's also not really elegant and is once again OOP, just not in the standard way.
Have each object have an "implements" array property, and leave the responsibility to the object to say if it implements a certain behavior, whether it is through composition or natively. Flexible and simple, but requires to remember a number of conventions. It is my preferred method until now, but I am still looking.
How would I initialize an object without repeating all the set-up for composited objects? For example, if I have an "textInput" class that uses a certain number of validators, which have to be initialized with variables, and a class "emailInput" which uses the exact same validators, it is cumbersome to repeat the code. And if the interface of the validators change, the code has to change in every class that uses them. How would I go about setting that easily? The API I am thinking of should be as simple as doing object.compositors('emailValidator','lengthValidator','...')
Is there any performance loss associated with having most of the functions that run in the app go through an apply()? Since I am going to be using delegation extensively, basic objects will most probably have almost no methods. All methods will be provided by the composited objects.
Any good resource? I have read countless posts about OOP vs delegation, and about the benefits of delegation, etc, but I can't find anything that would discuss "javascript delegation done right", in the scope of a large framework.
edit
Further explanations:
I don't have code yet, I have been working on a framework in pure OOP and I am getting stuck and in need of multiple inheritance. Thus, I decided to drop classes totally. So I am now merely at theoretical level and trying to make sense out of this.
"Compositing" might be the wrong word; I am referring to the composite pattern, very useful for tree-like structures. It's true that it is rare to have tree structures on the front end (well, save for the DOM of course), but I am developing for node.js
What I mean by "switching from OOP" is that I am going to part from defining classes, using the "new" operator, and so on; I intend to use anonymous objects and extend them with delegators. Example:
var a = {};
compositor.addDelegates(a,["validator", "accessManager", "databaseObject"]);
So a "class" would be a function with predefined delegators:
function getInputObject(type, validator){
var input = {};
compositor.addDelegates(input,[compositor,renderable("input"+type),"ajaxed"]);
if(validator){input.addDelegate(validator);}
return input;
}
Does that make sense?
1) How would I check if an object implements a certain behavior?
Most people don't bother with testing for method existance like this.
If you want to test for methods in order to branch and do different things if its found or not then you are probably doing something evil (this kind of instanceof is usually a code smell in OO code)
If you are just checking if an object implements an interface for error checking then it is not much better then not testing and letting an exception be thrown if the method is not found. I don't know anyone that routinely does this checking but I am sure someone out there is doing it...
2) How would I initialize an object without repeating all the set-up for composited objects?
If you wrap the inner object construction code in a function or class then I think you can avoid most of the repetition and coupling.
3) Is there any performance loss associated with having most of the functions that run in the app go through an apply()?
In my experience, I prefer to avoid dealing with this unless strictly necessary. this is fiddly, breaks inside callbacks (that I use extensively for iteration and async stuff) and it is very easy to forget to set it correctly. I try to use more traditional approaches to composition. For example:
Having each owned object be completely independent, without needing to look at its siblings or owner. This allows me to just call its methods directly and letting it be its own this.
Giving the owned objects a reference to their owner in the form of a property or as a parameter passed to their methods. This allows the composition units to access the owner without depending on having the this correctly set.
Using mixins, flattening the separate composition units in a single level. This has big name clash issues but allows everyone to see each other and share the same "this". Mixins also decouples the code from changes in the composition structure, since different composition divisions will still flatten to the same mixed object.
4) Any good resources?
I don't know, so tell me if you find one :)

The disadvantages of JavaScript prototype inheritance, what are they?

I recently watched Douglas Crockford's JavaScript presentations, where he raves about JavaScript prototype inheritance as if it is the best thing since sliced white bread. Considering Crockford's reputation, it may very well be.
Can someone please tell me what is the downside of JavaScript prototype inheritance? (compared to class inheritance in C# or Java, for example)
In my experience, a significant disadvantage is that you can't mimic Java's "private" member variables by encapsulating a variable within a closure, but still have it accessible to methods subsequently added to the prototype.
i.e.:
function MyObject() {
var foo = 1;
this.bar = 2;
}
MyObject.prototype.getFoo = function() {
// can't access "foo" here!
}
MyObject.prototype.getBar = function() {
return this.bar; // OK!
}
This confuses OO programmers who are taught to make member variables private.
Things I miss when sub-classing an existing object in Javascript vs. inheriting from a class in C++:
No standard (built-into-the-language) way of writing it that looks the same no matter which developer wrote it.
Writing your code doesn't naturally produce an interface definition the way the class header file does in C++.
There's no standard way to do protected and private member variables or methods. There are some conventions for some things, but again different developers do it differently.
There's no compiler step to tell you when you've made foolish typing mistakes in your definition.
There's no type-safety when you want it.
Don't get me wrong, there are a zillion advantages to the way javascript prototype inheritance works vs C++, but these are some of the places where I find javascript works less smoothly.
4 and 5 are not strictly related to prototype inheritance, but they come into play when you have a significant sized project with many modules, many classes and lots of files and you wish to refactor some classes. In C++, you can change the classes, change as many callers as you can find and then let the compiler find all the remaining references for you that need fixing. If you've added parameters, changed types, changed method names, moved methods,etc... the compiler will show you were you need to fix things.
In Javascript, there is no easy way to discover all possible pieces of code that need to be changed without literally executing every possible code path to see if you've missed something or made some typo. While this is a general disadvantage of javascript, I've found it particularly comes into play when refactoring existing classes in a significant-sized project. I've come near the end of a release cycle in a significant-sized JS project and decided that I should NOT do any refactoring to fix a problem (even though that was the better solution) because the risk of not finding all possible ramifications of that change was much higher in JS than C++.
So, consequently, I find it's riskier to make some types of OO-related changes in a JS project.
I think the main danger is that multiple parties can override one another's prototype methods, leading to unexpected behavior.
This is particularly dangerous because so many programmers get excited about prototype "inheritance" (I'd call it extension) and therefore start using it all over the place, adding methods left and right that may have ambiguous or subjective behavior. Ultimately, if left unchecked, this kind of "prototype method proliferation" can lead to very difficult-to-maintain code.
A popular example would be the trim method. It might be implemented something like this by one party:
String.prototype.trim = function() {
// remove all ' ' characters from left & right
}
Then another party might create a new definition, with a completely different signature, taking an argument which specifies the character to trim. Suddenly all the code that passes nothing to trim has no effect.
Or another party reimplements the method to strip ' ' characters and other forms of white space (e.g., tabs, line breaks). This might go unnoticed for some time but lead to odd behavior down the road.
Depending on the project, these may be considered remote dangers. But they can happen, and from my understanding this is why libraries such as Underscore.js opt to keep all their methods within namespaces rather than add prototype methods.
(Update: Obviously, this is a judgment call. Other libraries--namely, the aptly-named Prototype--do go the prototype route. I'm not trying to say one way is right or wrong, only that this is the argument I've heard against using prototype methods too liberally.)
I miss being able to separate interface from implementation. In languages with an inheritance system that includes concepts like abstract or interface, you could e.g. declare your interface in your domain layer but put the implementation in your infrastructure layer. (Cf. onion architecture.) JavaScript's inheritance system has no way to do something like this.
I'd like to know if my intuitive answer matches up with what the experts think.
What concerns me is that if I have a function in C# (for the sake of discussion) that takes a parameter, any developer who writes code that calls my function immediately knows from the function signature what sort of parameters it takes and what type of value it returns.
With JavaScript "duck-typing", someone could inherit one of my objects and change its member functions and values (Yes, I know that functions are values in JavaScript) in almost any way imaginable so that the object they pass in to my function bears no resemblance to the object I expect my function to be passed.
I feel like there is no good way to make it obvious how a function is supposed to be called.

Categories

Resources