Why is JavaScript prototyping? - javascript

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 :)

Related

Difference between creating an object through the prototype (not prototype framework) property vs jquery namespaced objects?

I just need to know what is the rudimentary difference between creating an object using these two methods, and the effect of using the objects.
//////////////////////////////////////////
myTestObject.prototype.var1 = null;
function myTestObject()
{
this.var1 = "test me";
}
myTestObject.prototype.action = function()
{
alert("alertme");
};
// to use
var a = new myTestObject();
a.action();
//////////////////////////////////////////
//////////////////////////////////////////
(function()
{
$.myTestObject3 = {
var1 : "test me",
action : _actionMethod
};
function _actionMethod()
{
alert("alertme3");
}
})();
$.myTestObject3.action();
//////////////////////////////////////////
A few updates... the answers to this question lead me to google for different keys words which lead to two interesting articles which really went into a lot of detail about Constructor vs Literal objects in javascript
http://net.tutsplus.com/tutorials/javascript-ajax/the-basics-of-object-oriented-javascript/
Then as a segue into why to use prototype when using function constructors paying particular attention to the section on Why is Using Prototype Better
http://net.tutsplus.com/tutorials/javascript-ajax/prototypes-in-javascript-what-you-need-to-know/?search_index=1
So as a follow up, you can use a combination of the two like in the guitar example below as a good practice. If only one copy of an object is needed and a change to it, knowing it affects the whole script is ok, then an object literal is fine. However if many objects need be created using the prototype approach is best so all created objects use a reference to the same function rather than having a copy of the function.
Another good article to make better use of namespacing and combining all these approaches
http://javascriptweblog.wordpress.com/2010/12/07/namespacing-in-javascript/
LAST FOLLOW-UP
I hope others find this useful as these topics threw me for a loop for a while.
Knowing what to look for now, I found two really good urls that describe many design patterns and how to intermix them in javascript using several examples.
This one describes how to use the module pattern in a way that makes use of the prototype notation. This will allow you to compartmentalize code while still making sure that instances are referencing the same objects.
http://briancray.com/posts/javascript-module-pattern/
This goes through several design patterns and list advatanges and disadvantages
http://addyosmani.com/resources/essentialjsdesignpatterns/book/
Take a look at Why is JavaScript prototyping? , some extract from there:
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)
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');
Objects using $ won't be able to use myTestObject3 because it has not been extended on the jQuert prototype. myTestObject3 is an object literal and not a constructor function.
$('#test').myTestObj3.action(); // wrong
If you wanted it to be on the prototype of jQuery, extend the $.fn object.
You can have an arbitrary amount of "children" deriving from myTestObject (the constructor) using prototypal inheritance.

custom methods and the usefulness of constructors and prototype in web-dev

ok so i know that prototype is used for inheritance and when coupled with a constructor function can be used to make custom methods. so my question here is two fold: how do i make methods for pre-built JavaScript objects like integers,strings,arrays,etc...
the other question is besides making my own methods what is the usefulness of constructors/prototype in everyday web development(i.e. creating websites) or is this more so for high-end development like making a web app or developing with new tech(i.e. html5 canvas or three.js) i haven't seen an example anywhere on the web of this being used in an everyday situation.
To create a Javascript method to an already existing object, you can simple add it to its constructor's prototype:
String.prototype.firstLetter = function() { return this.charAt(0); }
var myStr = "Cool str!";
alert(myStr.firstLetter()); // 'C'
As for how useful it will be, depends on what you do with Javascript. If you write client-side code and you need to modify an existing component, monkey-patching a function may be useful there. If you need some structure on your code (and you do), creating an object to represent the interface state may be useful.
Also, knowing how to use a tool usually avoids self-harm. =)
If you are interested, you may want to take a look into Crockford's page or buy his Javascript: The Good Parts book.
There is a lot of confusion you can avoid if you get to know the language, and you may even get to like it and find out you can do a lot of useful stuff in it.
Here's an example that extends Number:
Number.prototype.between = function(a, b) {
return this >= a && this <= b
}
var num = 0;
if (num.between(0,0)) alert('is between')
else alert('not');
Although I often use the prototype, I have not yet run across a good reason to use the constuctor property, which returns the type of an Object. W3schools.com has a good illustration of this property at http://www.w3schools.com/jsref/jsref_constructor_math.asp
You can add functions into a class's prototype:
String.prototype.report_fish = function() { alert("a fish!"); };
"".report_fish();
You can do this with numbers as well, although the syntax to invoke is slightly different:
Number.prototype.report_fish = function() { alert("a fish!"); };
(0).report_fish();
As to why you'd do this, I personally believe that you should avoid doing this to built-in objects where possible. (A persistent problem to work around when building re-usable Javascript libraries used to be and probably still is people's tendency to override and extend the Object prototype.)

Can you extend an object that has access to private properties with a function that can also access those private properties?

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.

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.)

Is JavaScript's "new" keyword considered harmful?

In another question, a user pointed out that the new keyword was dangerous to use and proposed a solution to object creation that did not use new. I didn't believe that was true, mostly because I've used Prototype, Script.aculo.us and other excellent JavaScript libraries, and everyone of them used the new keyword.
In spite of that, yesterday I was watching Douglas Crockford's talk at YUI theater and he said the exactly same thing, that he didn't use the new keyword anymore in his code (Crockford on JavaScript - Act III: Function the Ultimate - 50:23 minutes).
Is it 'bad' to use the new keyword? What are the advantages and disadvantages of using it?
Crockford has done a lot to popularize good JavaScript techniques. His opinionated stance on key elements of the language have sparked many useful discussions. That said, there are far too many people that take each proclamation of "bad" or "harmful" as gospel, refusing to look beyond one man's opinion. It can be a bit frustrating at times.
Use of the functionality provided by the new keyword has several advantages over building each object from scratch:
Prototype inheritance. While often looked at with a mix of suspicion and derision by those accustomed to class-based OO languages, JavaScript's native inheritance technique is a simple and surprisingly effective means of code re-use. And the new keyword is the canonical (and only available cross-platform) means of using it.
Performance. This is a side-effect of #1: if I want to add 10 methods to every object I create, I could just write a creation function that manually assigns each method to each new object... Or, I could assign them to the creation function's prototype and use new to stamp out new objects. Not only is this faster (no code needed for each and every method on the prototype), it avoids ballooning each object with separate properties for each method. On slower machines (or especially, slower JS interpreters) when many objects are being created this can mean a significant savings in time and memory.
And yes, new has one crucial disadvantage, ably described by other answers: if you forget to use it, your code will break without warning. Fortunately, that disadvantage is easily mitigated - simply add a bit of code to the function itself:
function foo()
{
// if user accidentally omits the new keyword, this will
// silently correct the problem...
if ( !(this instanceof foo) )
return new foo();
// constructor logic follows...
}
Now you can have the advantages of new without having to worry about problems caused by accidentally misuse.
John Resig goes into detail on this technique in his Simple "Class" Instantiation post, as well as including a means of building this behavior into your "classes" by default. Definitely worth a read... as is his upcoming book, Secrets of the JavaScript Ninja, which finds hidden gold in this and many other "harmful" features of the JavaScript language (the chapter on with is especially enlightening for those of us who initially dismissed this much-maligned feature as a gimmick).
A general-purpose sanity check
You could even add an assertion to the check if the thought of broken code silently working bothers you. Or, as some commented, use the check to introduce a runtime exception:
if ( !(this instanceof arguments.callee) )
throw new Error("Constructor called as a function");
Note that this snippet is able to avoid hard-coding the constructor function name, as unlike the previous example it has no need to actually instantiate the object - therefore, it can be copied into each target function without modification.
ES5 taketh away
As Sean McMillan, stephenbez and jrh noted, the use of arguments.callee is invalid in ES5's strict mode. So the above pattern will throw an error if you use it in that context.
ES6 and an entirely harmless new
ES6 introduces Classes to JavaScript - no, not in the weird Java-aping way that old-school Crockford did, but in spirit much more like the light-weight way he (and others) later adopted, taking the best parts of prototypal inheritance and baking common patterns into the language itself.
...and part of that includes a safe new:
class foo
{
constructor()
{
// constructor logic that will ONLY be hit
// if properly constructed via new
}
}
// bad invocation
foo(); // throws,
// Uncaught TypeError: class constructors must be invoked with 'new'
But what if you don't want to use the new sugar? What if you just want to update your perfectly fine old-style prototypal code with the sort of safety checks shown above such that they keep working in strict mode?
Well, as Nick Parsons notes, ES6 provides a handy check for that as well, in the form of new.target:
function foo()
{
if ( !(new.target) )
throw new Error("Constructor called as a function");
// constructor logic follows...
}
So whichever approach you choose, you can - with a bit of thought and good hygiene - use new without harm.
I have just read some parts of Crockford's book "JavaScript: The Good Parts". I get the feeling that he considers everything that ever has bitten him as harmful:
About switch fall through:
I never allow switch cases to fall
through to the next case. I once found
a bug in my code caused by an
unintended fall through immediately
after having made a vigorous speech
about why fall through was sometimes
useful. (page 97, ISBN
978-0-596-51774-8)
About ++ and --:
The ++ (increment) and -- (decrement)
operators have been known to
contribute to bad code by encouraging
excessive trickiness. They are second
only to faulty architecture in
enabling viruses and other security
menaces. (page 122)
About new:
If you forget to include the new
prefix when calling a constructor
function, then this will not be
bound to the new object. Sadly, this
will be bound to the global object, so
instead of augmenting your new object,
you will be clobbering global
variables. That is really bad. There
is no compile warning, and there is no
runtime warning. (page 49)
There are more, but I hope you get the picture.
My answer to your question: No, it's not harmful. but if you forget to use it when you should you could have some problems. If you are developing in a good environment you notice that.
In the 5th edition of ECMAScript there is support for strict mode. In strict mode, this is no longer bound to the global object, but to undefined.
JavaScript being a dynamic language, there are a zillion ways to mess up where another language would stop you.
Avoiding a fundamental language feature such as new on the basis that you might mess up is a bit like removing your shiny new shoes before walking through a minefield just in case you might get your shoes muddy.
I use a convention where function names begin with a lowercase letter and 'functions' that are actually class definitions begin with an uppercase letter. The result is a really quite compelling visual clue that the 'syntax' is wrong:
var o = MyClass(); // This is clearly wrong.
On top of this, good naming habits help. After all, functions do things and therefore there should be a verb in its name whereas classes represent objects and are nouns and adjectives without any verb.
var o = chair() // Executing chair is daft.
var o = createChair() // Makes sense.
It's interesting how Stack Overflow's syntax colouring has interpreted the code above.
I am newbie to JavaScript so maybe I am just not too experienced in providing a good view point to this. Yet I want to share my view on this "new" thing.
I have come from the C# world where using the keyword "new" is so natural that it is the factory design pattern that looks weird to me.
When I first code in JavaScript, I don't realize that there is the "new" keyword and code like the one in YUI pattern and it doesn't take me long to run into disaster. I lose track of what a particular line is supposed to be doing when looking back the code I've written. More chaotic is that my mind can't really transit between object instances boundaries when I am "dry-running" the code.
Then, I found the "new" keyword which, to me, "separates" things. With the new keyword, it creates things. Without the new keyword, I know I won't confuse it with creating things unless the function I am invoking gives me strong clues of that.
For instance, with var bar=foo(); I don’t have any clues as what bar could possibly be.... Is it a return value or is it a newly created object? But with var bar = new foo(); I know for sure bar is an object.
Another case for new is what I call Pooh Coding. Winnie-the-Pooh follows his tummy. I say go with the language you are using, not against it.
Chances are that the maintainers of the language will optimize the language for the idioms they try to encourage. If they put a new keyword into the language they probably think it makes sense to be clear when creating a new instance.
Code written following the language's intentions will increase in efficiency with each release. And code avoiding the key constructs of the language will suffer with time.
And this goes well beyond performance. I can't count the times I've heard (or said) "why the hell did they do that?" when finding strange looking code. It often turns out that at the time when the code was written there was some "good" reason for it. Following the Tao of the language is your best insurance for not having your code ridiculed some years from now.
I wrote a post on how to mitigate the problem of calling a constructor without the new keyword.
It's mostly didactic, but it shows how you can create constructors that work with or without new and doesn't require you to add boilerplate code to test this in every constructor.
Constructors without using "new"
Here's the gist of the technique:
/**
* Wraps the passed in constructor so it works with
* or without the new keyword
* #param {Function} realCtor The constructor function.
* Note that this is going to be wrapped
* and should not be used directly
*/
function ctor(realCtor) {
// This is going to be the actual constructor
return function wrapperCtor() {
var obj; // The object that will be created
if (this instanceof wrapperCtor) {
// Called with new
obj = this;
} else {
// Called without new. Create an empty object of the
// correct type without running that constructor
surrogateCtor.prototype = wrapperCtor.prototype;
obj = new surrogateCtor();
}
// Call the real constructor function
realCtor.apply(obj, arguments);
return obj;
}
function surrogateCtor() {}
}
Here's how to use it:
// Create our point constructor
Point = ctor(function(x, y) {
this.x = x;
this.y = y;
});
// This is good
var pt = new Point(20, 30);
// This is OK also
var pt2 = Point(20, 30);
The rationale behind not using the new keyword, is simple:
By not using it at all, you avoid the pitfall that comes with accidentally omitting it. The construction pattern that YUI uses, is an example of how you can avoid the new keyword altogether:
var foo = function () {
var pub = { };
return pub;
}
var bar = foo();
Alternatively, you could do this:
function foo() { }
var bar = new foo();
But by doing so you run risk of someone forgetting to use the new keyword, and the this operator being all FUBAR. As far as I know, there isn't any advantage to doing this (other than you being used to it).
At The End Of The Day: It's about being defensive. Can you use the new statement? Yes. Does it make your code more dangerous? Yes.
If you have ever written C++, it's akin to setting pointers to NULL after you delete them.
I think "new" adds clarity to the code. And clarity is worth everything. It is good to know there are pitfalls, but avoiding them by avoiding clarity doesn't seem like the way for me.
Case 1: new isn't required and should be avoided
var str = new String('asd'); // type: object
var str = String('asd'); // type: string
var num = new Number(12); // type: object
var num = Number(12); // type: number
Case 2: new is required, otherwise you'll get an error
new Date().getFullYear(); // correct, returns the current year, i.e. 2010
Date().getFullYear(); // invalid, returns an error
Here is the briefest summary I could make of the two strongest arguments for and against using the new operator:
Arguments against new
Functions designed to be
instantiated as objects using the
new operator can have disastrous
effects if they are incorrectly
invoked as normal functions. A
function's code in such a case will
be executed in the scope where the
function is called, instead of in
the scope of a local object as
intended. This can cause global
variables and properties to get
overwritten with disastrous
consequences.
Finally, writing function Func(),
and then calling Func.prototype
and adding stuff to it so that you
can call new Func() to construct
your object seems ugly to some
programmers, who would rather use
another style of object inheritance
for architectural and stylistic
reasons.
For more on this argument check out Douglas Crockford's great and concise book JavaScript: The Good Parts. In fact, check it out anyway.
Arguments in favor of new
Using the new operator along with
prototypal assignment is fast.
That stuff about accidentally
running a constructor function's
code in the global namespace can
easily be prevented if you always
include a bit of code in your
constructor functions to check to
see if they are being called
correctly, and, in the cases where
they aren't, handling the call
appropriately as desired.
See John Resig's post for a simple explanation of this technique, and for a generally deeper explanation of the inheritance model he advocates.
I agree with PEZ and some here.
It seems obvious to me that "new" is self descriptive object creation, where the YUI pattern Greg Dean describes is completely obscured.
The possibility someone could write var bar = foo; or var bar = baz(); where baz isn't an object creating method seems far more dangerous.
I think new is evil, not because if you forget to use it by mistake it might cause problems, but because it screws up the inheritance chain, making the language tougher to understand.
JavaScript is prototype-based object-oriented. Hence every object must be created from another object like so: var newObj=Object.create(oldObj). Here oldObj is called the prototype of newObj (hence "prototype-based"). This implies that if a property is not found in newObj then it will be searched in oldObj. newObj by default will thus be an empty object, but due to its prototype chain, it appears to have all the values of oldObj.
On the other hand, if you do var newObj=new oldObj(), the prototype of newObj is oldObj.prototype, which is unnecessarily difficult to understand.
The trick is to use
Object.create=function(proto){
var F = function(){};
F.prototype = proto;
var instance = new F();
return instance;
};
It is inside this function and it is only here that new should be used. After this, simply use the Object.create() method. The method resolves the prototype problem.
In my not-so-humble opinion, "new" is a flawed concept in 2021 JavaScript. It adds words where none are needed. It makes the return value of a function/constructor implicit and forces the use of this in the function/constructor. Adding noise to code is never a good thing.
// With new
function Point(x, y) {
this.x = x
this.y = y
}
let point = new Point(0, 0)
Vs.
// Without new
function Point(x, y) {
return { x, y }
}
let point = Point(0, 0)

Categories

Resources