JavaScript classes which cannot be subclassed - javascript

I have a JavaScript class, and I would like to make it so it can't be subclassed. (Similar to marking a class with the "final" keyword in Java.) Here's my JavaScript class:
function Car(make, model) {
this.getMake = function( ) { return make; }
this.getModel = function( ) { return model; }
}

The JavaScript Object Oriented paradigm is prototype based, that means that objects "inherit" from other objects, using them as their prototype.
There are no classes, Car is a constructor function, and the language lets you extend any virtually any object.
If you can make a Car object instance, there is no way to prevent this object being used as the prototype of other constructor function.

Given that JavaScript doesn't even actually have classes (it's a prototype-based object system, not a class-based one), and that it is a dynamic language[1], what you want to do is impossible. Further, JavaScript doesn't actually have inheritance/subclassing - it has to be faked by copying and extending objects. There is no way (that I know of) to prevent other code from doing this.
In a dynamic language with metaclass support, it would be possible to implement such a feature. JavaScript is not such a language.

Nope you can't do this directly and don't know that there is a way to do this given Javascript's prototypical inheritance but take a look at Extjs, which is a js framework which has a heavy object oriented type design. Look at the api and more so the source code and you might get closer to where you want to go -- but not totally :)

Related

Javascript OOP - abstraction (asking for example), encapsulation (grouping together properties/methods or keeping state private?), polymorphism

I know there are tons of oop posts on here as well as many blogs etc. I'm not posting this because im too lazy to read other posts, I probably read about 100 and still have some questions as many just state things but dont explain them much or certain things have contradicting answers and it would be great if I could get clear answers!
Encapsulation
There are posts that say yes to that because they define it as grouping together properties and functions. If that would be the definition, I totally get why javascript supports encapsulation. However, there also posts about keeping members private. As I understand (dont know java) but in Java thats the concept - you cannot access properties without methods (so only methods can access them) plus you actually have 'private/public' keywords to keep things private.
before ES6 :
Its possible:
function A (name) {
var name = name;
this.getName = function () {
return name;
}
}
var a = new A("mike");
a.getName() //accesses name
a.name //does not --> results in undefined
In es6 its not really possible, because you you would have to add the method accessing the property inside the constructor, which you wouldnt do
class A {
constructor(name) {
var name = name;
this.getName = () => {
return name; // only like this could you have var ...
}
}
}
So my question:
1. What is encapsulation ? Is it about grouping methods/properties or is it about keeping members private (which wouldnt be possible in es6 and before es6 not by default)?
Abstraction
" hiding internal implementation details. It should only reveal operations relevant for the other objects "
I would imagine for example jquery methods to use abstraction and you dont see their inner implemantion, 'just use' them. Could someone please explain and provide an example im vanilla js what abstraction is and if javascript actually makes use of that?
polymorphism
"designing objects to share behaviors and to be able to override shared behaviors with specific ones"
overriding
overloading
Many posts/blogs say polymorphism is NOT used in javascript, but..
Overloading is without argument not possible in javascript. Overriding of methods is?! I can have a parent class and a child class having the same function (same name) doing different things. Is that what you understand under overriding? Also, sharing behaviors is def. possible but only with inheritance.
Is there a way to share behaviors without inheritance, but only with making use of polymorphism? Im generally confused what exactly polymorphism is after reading for a while..
Inheritance
Inheritance is def. supported by js.
I just want to double check about es6 classes that I get it right (i have no experience with java etc).
The difference is that js uses prototypical inheritance and not classical as java etc. The difference is that when I create a new instance/=object from my es6 class, it links to properties/methods of the class that I use to initialize new objects, while in classical inheritance, the engine copies the properties/methods from that class. s that correct? Could someone please explain the difference - resulting - from that difference?

What advantages are gained by using constructors in JavaScript?

I'm working to refactor a large and undocumented JavaScript Library. One of the proposed refactorings is to implement constructors in the code as opposed to dynamically constructing an object. Example Below:
Instead of:
var myLibObj = new Object();
myLibObj.SomeProperty =
{
FooFunction: function(){/*Do Something Cool*/}
}
The proposed change:
function myLibObjConstructor(){
this.SomeProperty = {FooFunction: function(){/*Do Something Cool*/}}
return this;
}
var myLibObj = new myLibObjConstructor();
Is there any advantage to changing the code?
One advantage would be that myLibObjConstructor can be reused somewhere else
If it's existing code that already works without the need for constructors, the benefits of moving toward constructors could be marginal or non-existent.
However, the general advantages of using constructors would be:
Object instances have a "type" i.e. you can check instanceof or constructor to make decisions given just an object instance.
The most important of all, you get encapsulation. You can encapsulate "private" properties, inheritance etc., leading to cleaner and more portable code.
Using a constructor is more concise and more conventional than instantiating a generic object first and tacking on properties.
In other words, your question boils down to prototype vs constructors.
which is a great question and a lot has been written about it. Including here.
How to "properly" create a custom object in JavaScript?
Advantages of using prototype, vs defining methods straight in the constructor?
also good reading here:
http://mckoss.com/jscript/object.htm

Is there a way that Javascript can mimic an object oriented language?

I'm wondering if there is a way that Javascript can mimic an object oriented language. I.e. can you mimic the ability to define customized classes/objects with properties? Since JSON is basically a way of javascript passing objects, I figure there must be some way to create/store objects on the client side, then reuse them? If someone can point me to a good tutorial (if it's possible to do this at all) that would be much appreciated.
Even some example code where you can dynamically create an object, then consume it using jquery would be appreciated.
Javascript is an object oriented language, it's just not a class based object system, but a prototype based one. See this article: http://en.wikipedia.org/wiki/Prototype-based_programming
I found this to be a great tutorial: https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript
It must be said that Javascript is object oriented, however it is prototype based, rather than class based.
Douglas Crockford is a recognized person in JavaScript community,
His talks about JS are really good. In this series he talks about advanced js including object oriented javascript.
http://video.yahoo.com/video/play?vid=111585
http://video.yahoo.com/video/play?vid=111586
http://video.yahoo.com/video/play?vid=111587
Javascript is an Object Oriented language.
JavaScript is object oriented. It's just that it's prototype-based rather than class-based.
That said, JSON is not really suitable for serializing objects with inherited properties.
The short answer is "yes". There are a couple of excellent articles at developer.mozilla.org:
A re-introduction to JavaScript which includes its relationship to object-oriented languages
Introduction to Object-Oriented JavaScript
If you prefer an actual book, this has been very useful for me:
Pro Javascript Design Patterns
Although Javascript does not have a built-in class system (although the next version of Javascript might include this), there are many different Javascript OO Design Patterns that mimic the behavior of Classes. The Module pattern mimic's classes by allowing a Javascript object to hold both private and public members. This is achieved like so:
var Person = function() {
var firstName = "Greg";
var lastName = "Franko";
return {
getFirstName: function() {
return firstName;
},
getLastName: function() {
return lastName;
}
}
}
//Instantiate a new Person object
var greg = new Person();
//This will not work because the firstName property is private
console.log(greg.firstName);
//This will work because the getFirstName method is public
console.log(greg.getFirstName());

Why is JavaScript prototyping?

That may strike you as a grammatically incorrect and possibly insane question, but here's what I mean: When trying to understand the concept of prototype in JavaScript, I came upon examples that were slightly more or less complicated versions of the following:
//Guitar function constructor
function Guitar(color, strings) {
this.color = color;
this.strings = strings;
}
//Create a new instance of a Guitar
var myGuitar = new Guitar('Black', ['D', 'A', 'D', 'F', 'A', 'E']);
//Adding a new method to Guitar via prototype
Guitar.prototype.play = function (chord) {
alert('Playing chord: ' + chord);
};
//Now make use of this new method in a pre-declared instance
myGuitar.play('D5');
So, on to my problem: Why the hell would you want to do this? Why would you not just put the play function in Guitar to begin with? Why declare an instance and then start adding methods later? The only reason I can see is if you wanted myGuitar to not have access to play when it is originally created, but I can come up with no example that elucidates a reason as to why you would want something like this.
It seems like it would make more sense to do this:
function Guitar(color, string) {
this.color = color;
this.strings = strings;
this.play = function (chord) {
alert('Playing chord: ' + chord);
};
}
var myGuitar = new Guitar('White', ['E', 'A', 'D', 'G', 'B', 'E']);
myGuitar.play('E7#9');
The real problem here is that the second example makes sense to me while the first example does not, whereas in reality, the first example is probably better for some reason(s). Unfortunately, every tutorial I have ever found just goes through the steps of using prototype but not why the prototype paradigm exists at all to begin with.
It seems that prototype allows you to do things that you would not otherwise be able to do, but I can come up with no good reasons as to why you would want to do them.
Edit: Some responses:
When I said "Why declare an instance and then start adding methods later?" I was more critiquing all of the examples I see that play out in the order of my first example. When this order is changed, as in Harmen's response below, it does make slightly more sense visually. However, this doesn't change the fact that, in the same vein as my first example, you can create an empty object function constructor, declare 100 instances of this object, and then only afterwards define what the original object actually is by giving it methods and properties via prototype. Perhaps this is generally done this way to hint at the Copy vs. Reference idea outlined below.
Based on several responses, here is my new understanding: If you add all of your properties and methods to the object function constructor, then create 100 instances of that object, you get 100 copies of all of the properties and methods. Instead, if you add all of your properties and methods to the prototype of the object function constructor, then create 100 instances of that object, you get 100 references to the single (1) copy of the object's properties and methods. This is obviously faster and more efficient and is why prototype is used (aside from altering things like String and Image, as mentioned below). So, why not do this:
(Bulleted lists break any code right after them, apparently, so I have to add a line of separate text here)
function Guitar(color, strings) {
this.prototype.color = color;
this.prototype.strings = strings;
this.prototype.play = function (chord) {
alert('Playing chord: ' + chord);
};
}
var myGuitar = new Guitar('Blue', ['D', 'A', 'D', 'G', 'B', 'E']);
myGuitar.play('Dm7');
So, on to my problem: Why the hell would you want to do this? Why would you not just put the play function in Guitar to begin with? Why declare an instance and then start adding methods later?
Javascript is not a 'classical' inheritance language. It uses prototypal inheritance. Its just the way it is. That being the case, the proper way to create an method on a 'class' is to put the method on the prototype. Note that I put 'class' in quotes, since strictly speaking JS has no notion of 'class'. In JS, you work on objects, which are defined as functions.
You can declare the method in the function that defines Guitar, however, when you do that, every new guitar gets its own copy of the play method. Putting it on the prototype is more efficient in the runtime environment when you start creating Guitars. Every instance shares the same play method, but the context/scope is set when invoked so it acts a proper instance method you are used to in your classical inheritance language.
Note the difference. In the 'why not this way' example you posted, every time you create a new Guitar, you need to create a new play method that is the same as every other play method. If play is on the prototype, however, all Guitars borrow from the same prototype, so they all share the same code for play. Its the difference between x number of guitars, each with identical play code (so you have x copies of play) vs x number of guitars sharing the same play code (1 copy of play no matter how many Guitars). The trade off is of course that at runtime play needs to be associated with the object on which it is called for scoping, but javascript has methods that allow you to do that very efficiently and easily (namely the call and apply methods)
Many javascript frameworks define their own utilities for creating 'classes'. Typically they allow you to write code like the example you said you would like to see. Behind the scenes, they are putting the functions on the prototype for you.
EDIT -- in answer to your updated question, why can't one do
function Guitar() {
this.prototype.play = function()....
}
it has to do with how javascript creates objects with the 'new' keyword. See the second answer here -- basically when you create an instance, javascript creates the object and then assigns the prototype properties. So this.prototype.play doesn't really make sense; in fact, if you try it you get an error.
As a note before beginning -- I am using ECMAScript here instead of JavaScript as ActionScript 1 and 2 exhibit exactly the same behavior at runtime.
Those of us who work in a more "traditional" object oriented world (read Java/C#/PHP) find the idea of extending a class at runtime almost entirely foreign. I mean, seriously, this is supposed to be my OBJECT. My OBJECT will go forth and DO THINGS which have been SET FORTH. Child classes EXTEND other CLASSES. It has a very structured, solid, set in stone feeling to it. And, for the most part, this works and it works reasonably well. (And this is one of the reasons Gosling has argued, and I think most of us would agree fairly effectively, that it is so well suited to massive systems)
ECMAScript, on the other hand, follows a much more primative concept of OOP. In ECMAScript, class inheritance is entirely, believe it or not, a gigantic decorator pattern. But this isn't just the decorator pattern you might say is present in C++ and Python (and you can easily say that those are decorators). ECMAScript lets you assign a class prototype to an instance.
Imagine this happening in Java:
class Foo {
Foo(){}
}
class Bar extends new Foo() {
// AAAHHHG!!!! THE INSANITY!
}
But, that is exactly what is available in ECMAScript (I believe Io also allows for something like this, but don't quote me).
The reason I said that this is primitive is that this type of design philosophy is very much linked up with the way that McCarthy used Lambda Calculus to implement Lisp. It has more to do with the idea of closures than, say, Java OOP does.
So, back in the day, Alonzo Church wrote The Calculi Lambda Conversion, the seminal work in Lambda Calculus. In it he proposes two ways of looking at multi-argument functions. First, they can be considered to be functions which accept singletons, tuples, triples, etc. Basically f(x,y,z) would be understood as f which accepts the parameter (x,y,z). (By the way, it is my humble opinion that this is a primary impetus for the structure of Python’s argument lists, but that is conjecture).
The other (and for our purposes (and, to be honest, Church’s purposes) more important) definition was picked up by McCarthy. f(x,y,z) should be translated instead to f(x g(y h(z))). Resolution of the outermost method could come from a series of states which were generated by the internal function calls. That stored, internal state is the very basis of the closure, which, in turn, is one of the bases for modern OOP. Closures allow for passing enclosed, executable states between different points.
A diversion courtesy of the book Land Of Lisp:
; Can you tell what this does? It it is just like your favorite
; DB’s sequence!
; (getx) returns the current value of X. (increment) adds 1 to x
; The beauty? Once the let parens close, x only exists in the
; scope of the two functions! passable enclosed executable state!
; It is amazingly exciting!
(let (x 0)
; apologies if I messed up the syntax
(defun increment ()(setf x (+ 1 x)))
(defun getx ()(x)))
Now, what does this have to do with ECMAScript vs. Java? Well, when an object is created in ECMAScript it can follow that pattern almost exactly:
function getSequence()
{
var x = 0;
function getx(){ return x }
function increment(){ x++ }
// once again, passable, enclosed, executable state
return { getX: getX, increment:increment}
}
And here is where the prototype starts coming in. Inheritance in ECMAScript means, “start with object A and add to it.” It does not copy it. It takes this magical state and ECMAScript appends it. And that is the very source and summit of why it must allow for MyClass.prototype.foo = 1.
As to why you would append methods “after the fact”. For the most part it boils down to style preferences really. Everything which happens inside of the original definition is doing no more than the same type of decoration which happens outside.
For the most part it is stylistically beneficial to put all of your definitions in the same place, but sometimes that is not possible. jQuery extensions, for example, work based on the idea of appending the jQuery object prototype directly. The Prototype library actually has a specialized way of expanding class definitions which it uses consistently.
If I remember Prototype.js correctly, it is something like this:
var Sequence = function(){}
// Object.extend takes all keys & values from the right object and
// adds them to the one on the left.
Object.extend( Sequence.prototype, (function()
{
var x = 0;
function getx(){ return x }
function increment(){ x++ }
return { getX: getX, increment:increment}
})());
As to use of the prototype keyword inside of the original definition, well, that won’t work in most cases because “this” refers to an instance of the object being defined (at the time when the instance is constructed). Unless the instance also had a “prototype” property, this.prototype would necessarily be undefined!
Since all of the this’s inside of the original definition will be instances of that object, modifying this would be sufficient. But, (and I smile as I say this because it goes right along with prototype) each this has a constructor property.
// set the id of all instances of this “class”. Event those already
// instantiated...
this.constructor.prototype.id = 2
console.log( this.id );
If you don't use the prototype, every time you call the constructor of Guitar, you will create a new function. If you are creating a lot of Guitar objects, you will notice a difference in performance.
Another reason to use prototypes is to emulate classical inheritance.
var Instrument = {
play: function (chord) {
alert('Playing chord: ' + chord);
}
};
var Guitar = (function() {
var constructor = function(color, strings) {
this.color = color;
this.strings = strings;
};
constructor.prototype = Instrument;
return constructor;
}());
var myGuitar = new Guitar('Black', ['D', 'A', 'D', 'F', 'A', 'E']);
myGuitar.play('D5');
In this example, Guitar extends Instrument, and therefore has a 'play' function. You can also override the Instrument's 'play' function in Guitar if you like.
JavaScript is a prototypical language, a rather rare breed. This is not arbitrary at all, it's a requirement of a language that is live evaluated and capable of "eval", dynamic modifications, and REPL.
Prototypical inheritence can be understood as compared to Object Oriented Programming based on runtime "live" class definitions instead of static predefined ones.
Edit: another explanation stolen from from the following link is also useful. In an Object Oriented Language (Class -> Object/Instance) all the possible properties of any given X are enumerated in Class X, and an instance fills in its own specific values for each of them. In prototypical inheritance you only describe the differences between existing reference to live X and similar but different live Y, and there is no Master Copy.
http://web.media.mit.edu/~lieber/Lieberary/OOP/Delegation/Delegation.html
First off you need to understand the context. JavaScript is an interpreted language that is executed and can be modified in a live environment. The program's internal structure itself can be modified at runtime. This places different constraints and advantages from any compiled language, or even CLR linked language such as .Net stuff.
The concept of "eval"/REPL requires dynamic variable typing. You can't effectively live-edit an environment where you have to have predefined monolithic Class based inheritances structures. It's pointless, you might as well just precompile to assembly or bytecode.
Instead of that we have prototypical inheritance where you link the properties of an INSTANCE of an object. The concept is if you're in an all-live environment, classes (static, predefined constructs) are unnecessarily limiting. Classes are built on constraints that don't exist in JavaScript.
With this strategy JavaScript basically banks on everything being "live" Nothing is off-limits, there's no "defined and done" classes you can never touch. There's no "One True Scotsmen" among variables that is holier than your code because everything obeys the same rules as the code you decide to write today.
The consequences of this are pronounced, and also very much human based. It pushes language implementers to use a light, efficient touch in providing native objects. If they do a poor job them the mob will simply usurp the platform and rebuild their own (read the source of MooTools, it literally redefines/reimplements everything, starting from Function and Object) . This is how compatibility is brought to platforms like old Internet Explorer versions. It promotes libraries that are shallow and narrow, densely functional. Deep inheritance results in the most used parts being (easily) cherry picked out and becoming the ultimate go-to library. Wide libraries result in fracturing as people pick and choose which pieces they need, because taking a bite out is easy, instead of impossible as in most other environments.
The concept of micro libraries is uniquely flourishing in JavaScript and it absolutely can be traced back to the fundamentals of the language. It encourages efficiency and brevity in terms of human consumption in ways no other language (that I know of) promote.
The first method you give is faster, and it really begins to make sense when you write it in another order:
//Guitar function constructor
function Guitar(color, strings) {
this.color = color;
this.strings = strings;
}
Guitar.prototype.play = function (chord) {
alert('Playing chord: ' + chord);
};
var myGuitar = new Guitar('Black', ['D', 'A', 'D', 'F', 'A', 'E']);
It is faster because Javascript does not need to execute the constructor to create the variables, it can just use the predefined variables of the prototype.
For a proof, see this speed test on a question that is much like this one.
And maybe this alternative version makes even more sense to you:
function Guitar(){
// constructor
}
Guitar.prototype = {
play: function(a){
alert(a);
},
stop: function(){
alert('stop it');
}
};
For one thing, you can use prototype to extend objects that are built into the JavaScript language (like String). I prefer the second example for custom objects.
Javascript is prototypal based. When in Rome, do as Romans do so when in JS, use prototypal inheritance.
It's more efficient because the method becomes inherited on each object. If it wasn't a prototypal method then every instance of that object would each have its own play method. Why go the inefficient route and non-traditional to JS route when we can go the efficient and natural to JS route?
You already have a lot of good answers that is why I'm not going through all of your points.
Why declare an instance and then start adding methods later?
That is not correct. The prototype object exists independently of every instance. It is a property of the function object (the constructor function).
When you create a new instance it "inherits" all the properties from the prototype (in fact, it has a reference to it).
Actually it makes sense if you think about objects and references: It is better (memory-wise) to share one reference to an object than each instance having its own copy of an object (the object in this case would be the function play).
As to why it is prototype based: You could also ask why different language paradigms exist (functional, oo, declarative). There is no only one correct way to do something.
It is based on the Prototype creational design pattern. This Wikipedia link has a nice discussion.
http://en.wikipedia.org/wiki/Prototype_pattern
Bro let me ask you one thing, what If you have Guitar, Casio, Violin and you want play same chords in each of these musical instrument.
So I guess why don't we keep one function play_chord separately and use this(play_chord) function with any of above instrument, instead using each function inside Guitar, casio or violin.
so finally whenever we need a function which could be part of other constructor then we should define that particular function inside prototype and use accordingly :)

Is John Resig's OO JavaScript implementation production safe?

For a long time I have been throwing around the idea of making my JavaScript more object oriented. I have looked at a few different implementations of this as well but I just cannot decide if it is necessary or not.
What I am trying to answer are the following questions
Is John Resig's simple inheritance structure safe to use for production?
Is there any way to be able to tell how well it has been tested?
Besides Joose what other choices do I have for this purpose? I need one that is easy to use, fast, and robust. It also needs to be compatible with jQuery.
Huh. It looks much more complicated than it needs to be, to me.
Actually looking more closely I really take exception to what it is doing with providing this._super() whilst in a method, to call the superclass method.
The code introduces a reliance on typeof==='function' (unreliable for some objects), Function#toString (argh, function decomposition is also unreliable), and deciding whether to wrap based on whether you've used the sequence of bytes _super in the function body (even if you've only used it in a string. and if you try eg. this['_'+'super'] it'll fail).
And if you're storing properties on your function objects (eg MyClass.myFunction.SOME_PRIVATE_CONSTANT, which you might do to keep namespaces clean) the wrapping will stop you from getting at those properties. And if an exception is thrown in a method and caught in another method of the same object, _super will end up pointing at the wrong thing.
All this is just to make calling your superclass's method-of-the-same name easier. But I don't think that's especially hard to do in JS anyway. It's too clever for its own good, and in the process making the whole less reliable. (Oh, and arguments.callee isn't valid in Strict Mode, though that's not really his fault since that occurred after he posted it.)
Here's what I'm using for classes at the moment. I don't claim that this is the “best” JS class system, because there are loads of different ways of doing it and a bunch of different features you might want to add or not add. But it's very lightweight and aims at being ‘JavaScriptic’, if that's a word. (It isn't.)
Function.prototype.makeSubclass= function() {
function Class() {
if (!(this instanceof Class))
throw 'Constructor function requires new operator';
if ('_init' in this)
this._init.apply(this, arguments);
}
if (this!==Object) {
Function.prototype.makeSubclass.nonconstructor.prototype= this.prototype;
Class.prototype= new Function.prototype.makeSubclass.nonconstructor();
}
return Class;
};
Function.prototype.makeSubclass.nonconstructor= function() {};
It provides:
protection against accidental missing new. The alternative is to silently redirect X() to new X() so missing new works. It's a toss-up which is best; I went for explicit error so that one doesn't get used to writing without new and causing problems on other objects not defined like that. Either way is better than the unacceptable JS default of letting this. properties fall onto window and mysteriously going wrong later.
an inheritable _init method, so you don't have to write a constructor-function that does nothing but call the superclass constructor function.
and that's really all.
Here's how you might use it to implement Resig's example:
var Person= Object.makeSubclass();
Person.prototype._init= function(isDancing) {
this.dancing= isDancing;
};
Person.prototype.dance= function() {
return this.dancing;
};
var Ninja = Person.makeSubclass();
Ninja.prototype._init= function() {
Person.prototype._init.call(this, false);
};
Ninja.prototype.swingSword= function() {
return true;
};
var p= new Person(true);
p.dance(); // => true
var n = new Ninja();
n.dance(); // => false
n.swingSword(); // => true
// Should all be true
p instanceof Person &&
n instanceof Ninja && n instanceof Person
Superclass-calling is done by specifically naming the method you want and calling it, a bit like in Python. You could add a _super member to the constructor function if you wanted to avoid naming Person again (so you'd say Ninja._super.prototype._init.call, or perhaps Ninja._base._init.call).
JavaScript is prototype based and not class based. My recommendation is not to fight it and declare subtypes the JS way:
MyDerivedObj.prototype = new MySuperObj();
MyDerivedObj.prototype.constructor = MyDerivedObj;
See how far you can get without using inheritance at all. Treat it as a performance hack (to be applied reluctantly where genuinely necessary) rather than a design principle.
In an a highly dynamic language like JS, it is rarely necessary to know whether an object is a Person. You just need to know if it has a firstName property or an eatFood method. You don't often need to know if an object is an array; if it has a length property and some other properties named after integers, that's usually good enough (e.g. the Arguments object). "If it walks like a duck and quacks like a duck, it's a duck."
// give back a duck
return {
walk: function() { ... },
quack: function() { ... }
};
Yes, if you're making very large numbers of small objects, each with dozens of methods, then by all means assign those methods to the prototype to avoid the overhead of creating dozens of slots in every instance. But treat that as a way of reducing memory overhead - a mere optimisation. And do your users a favour by hiding your use of new behind some kind of factory function, so they don't even need to know how the object is created. They just need to know it has method foo or property bar.
(And note that you won't really be modelling classical inheritance in that scenario. It's merely the equivalent of defining a single class to get the efficiency of a shared vtable.)

Categories

Resources