Im a bit confused learning all the new ES6 vs ES5 syntax with javascript and when it comes to functions/classes with methods and calling upon those methods I can't really tell what is the "right way".
For example take this code:
function account(amount) {
let cash = amount;
this.setCash = function(amt)
{
cash = amt;
}
this.getCash = function()
{
return cash;
}
}
var person = new account(100);
console.log(person.getCash()); //returns 100
person.setCash(150);
console.log(person.getCash()); //returns 150
Works like normal as expected (This is how I originally saw the methods being used when going through tutorials).
However i've seen this occasionally:
function account2(amount) {
let cash = amount;
function setCash(amt)
{
cash = amt;
}
function getCash()
{
return cash;
}
return{
getCash,
setCash
}
}
var person2 = new account2(50);
console.log(person2.getCash()); //returns 50
person2.setCash(175);
console.log(person2.getCash()); //returns 175
Both of these work perfectly fine, and do as I think they should. However is one just an older way of doing it? or less correct maybe? This is my biggest barrier in learning JS right now, since ES6 is here there are so many different ways to do something as simple as making a "class" in JS with methods.
Personally the first way seems easier since you don't have to return the functions....but for example at work I see the 2nd way used mostly?
If you removed new from the second version (more on that in a moment) then both of your examples are perfectly fine ways of creating an object with private data accessed via public get/set methods. Which one you would choose is personal preference, or dependent on whether you want to extend the functionality further with prototype methods, etc.
The reason I suggest removing new from the second version is that although both examples work, the first is a "normal" use of the new operator, but the second is an "incorrect" use of the new operator - not a syntax error, just semantically incorrect and potentially misleading for other people reading your code.
So why is that second use of new semantically incorrect? When you say var person = new account(100):
A new object is created with a prototype that is account.prototype. That means the new object inherits any methods and properties of the account.prototype, and from its prototype, etc. (In your case you haven't defined any methods on the prototype, but you could.)
Within the account() function, this will refer to the object created in step 1. Which is why you can attach methods to it with this.setCash = ...
The new object is returned from account() by default. This step will not occur if there is an explicit return statement returning something else as in your account2() function.
So in the first example, person instanceof account is true, because the default object was returned. In the second example, person2 instanceof account2 is false, because a different object was returned - this is misleading for people reading your code, because when they see person2 = new account2() they might reasonably expect that person2 will be an instance of account2 but it's not. It's also a bit inefficient, because the JS engine goes to the trouble of creating an object for you and then you don't use it.
So the second example would be more "correct" without new, providing the same behaviour minus the unnecessary auto object creation:
var person2 = account2(50);
(Almost) any JS function that you write can be called with new, but there is a convention that we describe functions intended to be called with new as "constructors", and usually the function name is capitalised, so Account(), not account(). (The spelling doesn't change the behaviour, it's just an extra hint for people reading the code.)
Note that use of new isn't the only way to link objects to particular prototypes: it is the old-school-but-still-perfectly-valid way, but you can use Object.create() instead.
By the way, the behaviour in question is not new in ES5 or 6, though let and the shortcut object literal syntax in account2 are new.
When you create an instance with new keyword this is returned implicitly where as when assign a function to a variable without new, you need to use return explicitly.
I am creating an object inside of an enclosure. Also in the enclosure are private properties that the object's functions can access - and this works as expected.
My issue: I want others to be able to extend my object with functions of their own (functions from a different context), but those functions will also need access to the same private properties - and I have not been able to find a way to make this work.
I've tried various configurations of .call, and also wrapping their function in a new function, amongst other things. I feel like I've gotten close to a solution, but have just fallen short.
Here's a bit of simplified example code that accurately reflects my situation:
//extension object
//fn2 can be any function, with any number of arguments, etc.
var obj1 = {};
obj1.fn2 = function (s1, s2){ console.log(priv); };
//actual object
var obj2 = (function (){
//private property
var priv = "hello world";
//return object
var obj3 = {};
//return object's native fn (works)
obj3.fn = function (s){ console.log(priv); };
//extension happens here - but is obviously not correct
obj3.fn2 = obj1.fn2;
//return object
return obj3;
})();
//try output
obj2.fn("goodbye world"); //works
obj2.fn2("goodbye world", "thx 4 teh phish"); //fails
Any insight would be appreciated. And I totally understand if what I want just isn't possible - but it sure seems like it should be :P
EDIT: Thank you all for the responses. I fully understand that the properties are more easily accessed as public, and that normally inherited objects won't have access to them otherwise. However, since the new function is being attached to the original object I have to believe there's a way to use the original context and not the context the new function was created in.
Now, I'm the first to say that eval is evil - and, in fact, I've never used it, or even considered using it, before. However, I'm trying everything I can think of to make this work - and I stumbled across this (seemingly) working solution:
obj3.fn2 = eval(obj1.fn2.toString());
So, if I check to make sure that obj1.fn2 is a typeof function, is there any way this could be harmful to my code? It doesn't execute the function, so I can't see how - but maybe I'm missing something?
Javascript doesn't have a "protected" analog. You either get super private or completely public. From here you can choose to:
Reconsider your class design, and have the subclasses depend only on the public interface of the parent class.
Add getter and setter functions to the public interface. Not necessarily the best thing though as you might just as well make the properties public (besides best practice issues and whatnot)
Just use public properties instead. This is the "natural" way to do OO inheritance in Javascript and is usually not a problem if you use a donvention like adding an underscore to the beggining of the name. As a bonus you can use the prototypal inheritance feature (it is nice knowing how to use this instead of only closure-based classes)
function Base(){
this._priv = "Hello world"
};
Base.prototype = {
fn: function(){
console.log(this._priv);
}
}
var obj2 = new Base();
obj2.fn = function(){ ... }
I hate to answer my own question - seems like a bit of a faux pas - but c'est la vie. (because I woke up French today?)
So, while I found that the eval() solution I presented last night in the edit to my original question does seem to be a valid solution, and a proper use of eval for retaining the object's context within the new function, it is far from perfect.
Firstly, it works in FF, but both IE and Chrome seem to hate it (those were the next ones I tried, and I quit trying others after they both failed). Though I'm sure it could probably be made to work across browsers, it seems like a hassle.
Secondly, it does give quite a bit of power to the new function, and as I look at my code more I do like the idea of controlling exactly what these new functions being added to my object get access to.
Thirdly, .eval() is typically pretty slow - and it turns out that .apply() (which is typically faster) just may work well enough.
This is because I realized at some point last night that no new functions on this object will need to set any of the private variables (at least, I'm fairly certain they won't) - and .apply() works fine to pass the values through for them to read.
I'm sure there's more to it than just those 3 things, but for now I think I'm going to go with more of a 'wrapper' solution - something like this:
var f = function (){
var fauxThis = {};
fauxThis.priv = priv;
obj1.fn2.apply(fauxThis, arguments);
};
obj3.fn2 = f;
//(To be placed where I had "obj3.fn2 = obj1.fn2;")
I am certainly willing now to consider the use of eval() in very specific cases - and may even revisit this specific use of it before I make my final decision of which direction to take. (especially if I can think of a case where the private value would need to be set)
Thanks all for your input!
The quickest and easiest solution is to prefix any supposedly private properties with the underscore (_).
Personally I like to bottle my private properties into a single object which would be placed on the object, like so:
obj.publicProp = 20;
obj._.privateProp = true;
I wouldn't worry so much about it though, the underscore is basically a universal symbol for private so those using the script will know that it's private and shouldn't be touched. Or, better yet, just leave it out of the public documentation ;)
There are other methods and you can use which do emulate "true" protected variables, but they're not the best as they avoid garbage collection, and can be clunky to use.
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 :)
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.)
In the ASP.NET ajax library, there is a line that makes me confused.
Type.prototype.registerClass = function Type$registerClass(typeName, baseType, interfaceTypes) {
//..
this.prototype.constructor = this;
//..
}
I know that (this.prototype.constructor === this) == true, so what is significance of this line? I remove the line, and test the library with some code. It seems it is okay. What is the purpose of this line?
I'm not familiar with the asp.net libs, but:
A common pattern in Javascript, especially when trying to simulate class based systems, is to reassign the prototype object to an instance of another object, rather than just adding properties to the prototype object JS gives you. One issue with this is that it gives you the wrong constructor - unless perhaps one resets with a 'correct' value.
My guess would be that at some point before this.prototype.constructor = this;, some object was assigned to the prototype property, which overwrote prototype.constructor. This trick is often used when inheriting object prototypes easily, but still being able to call instanceof to see whether an object instance is of a certain type.
Hard to tell anything more specific than that in this case and a seriously old question, however it might be useful to somebody.