8 ms·
A minimalist approach to OOP in Javascript
- stephenr 15y agoI really don't understand the great lengths people go to, to avoid the "new" operator in JavaScript. This example is horrendous IMO. One of the biggest strengths of JS is the use of prototypes, but people still persist with shit like returning object literals with methods directly defined on them..
- TazeTSchnitzel 15y agoWell, constructor functions called without the new operator have disastrous effects. Although that's probably not the prime motivation. There's several different OOP styles in JS, and I quite like this one. Not using prototypes means you can create uncompromisable objects with inheritance.
- stephenr 15y agoIt's fairly trivial to check if a constructor was called without the new operator.
- gabordemooij 15y agoNo, prototypes are a wrong idea. They are both complex and dangerous. Complex because you have to add methods indirectly and yet there are no classes (I mean, seriously... how can anyone claim this makes sense?). Dangerous because you can easily break native functions like toString().
- stephenr 15y agoYou can override the tostring method on any object. You can override any method on any object - JS is a dynamic language, not using new & prototypes won't change that.
- gabordemooij 15y agoThis is not true. With prototypes you can override default functionality thus introducing unexpected behaviours. While you can indeed override individual instance methods with augmentation, you cannot override the 'general' toString() function. str = 'a'; str.toString = null str.toString(); //still works str = new String(); str.toString = null; str.toString(); //fails str2 = new String(); str.toString(); //still works but: String.prototype.toString = null; str = new String(); str.toString(); //unexpected error
- russfrank 15y agoThat's because "override the 'general' toString() function" doesn't make sense. This is a method. It must be overriden for a particular class of objects. The first part of your example is due to the conversion between primitives and objects for method calls. It has little to do with prototypal inheritance. Then, you override the method on an instance of String. When you set toString to null, of course, the call to toString fails. Lastly, you override it on the prototype of String, which will apply to all String objects. Why is this an unexpected error? toString is on the prototype, because it's defined on the class, not the instance. I'm not sure what the confusion is here.
- stephenr 15y agoYou're suggesting that the ability to provide a "toString" method on a custom object type (aka "Class") is a bad thing, because if you set it to NULL, it will fail when called? Seriously? By your logic, cars are bad because if you run a pipe from the exhaust to the inside of the car and sit in it with the engine running, it will kill you. Any developer can do stupid things in any language, with any code pattern, and trying to use that as a reason not to take advantage of a language's features is ridiculous.
- huskyr 15y agoI don't really get why you would need a createNew() method in this setup. Why not simply have a function that returns an object? function Cat() { var private; function meow() { alert('meow'); } return { meow : meow }; } var cat = Cat();
- chrisbroadfoot 15y ago> Note that we did not use a lot of confusing JS stuff: no this, no new, no prototype Makes as much sense to me as it did to you. That is, very little. I wish the author would properly explain why he went to great lengths to avoid the tools available to him.
- TazeTSchnitzel 15y agoI don't know the author's reasoning, but I read Crockford's JavaScript: The Good Parts, which demonstrates several OOP styles (including this one). One of the reasons he likely didn't use the "this" keyword is because it's compromisable. "this" is anything that the invoker of the method wants it to be, so you can accidentally compromise information. Also, if you have your variables in function scope and the function is created in that scope, the keyword is unnecessary. Regarding not using new/constructor functions, some people think the non-constructor-based OOP model in JS is nicer. Finally, regarding lack of prototypes, if you want to keep secrets then you can't re-use functions. On the other hand, if you are creating public/non-privileged methods, no reason not to re-use functions.
- TazeTSchnitzel 15y agoI think it's worth noting this doesn't follow good JavaScript naming practices. Due to the disastrous effects of constructor functions if used without the new keyword, only constructor functions should have a capitalised first letter such that they can be easily distinguished.
- Jebus 15y agoOh no, please not another OOP javascript tutorial without prototypes.
- TazeTSchnitzel 15y agoWhat's wrong with not using prototypal inheritance? There are several styles of JavaScript OOP. You don't have to use constructor functions. Unless you mean the .prototype property, in which case you really mean re-use of functions. That's something you can only use for unsafe public methods, unfortunately. For safe (uncompromisable) public methods it can't be used, nor can it for private or privileged methods.
- TazeTSchnitzel 15y agoSo you basically just came up with what Crockford calls the 'Functional' method of creating objects? Why duplicate effort in describing the concept?
- J3L2404 15y agoI find it a continuing source of confusion that people can't distinguish between a person who submits an item, and the author of the item being submitted. I submitted this item. I did not write it. The person who wrote it did not submit this to HackerNews.
- TazeTSchnitzel 15y agoI realised that when I posted it. There doesn't seem to be a comments field on the site, unfortunately. So this only serves as a heads-up to other people on Hacker News.
- J3L2404 15y agoYou "realized that" but still used "you". I don't understand.
- gabordemooij 15y agoNo, it isnt. It's cleaner because the class-object is an object instead of a function, this makes it possible to add static methods.
- stephenr 15y agoYou can have "static methods" on a prototype constructor. Functions are objects, so adding a static property to a constructor function is no harder than adding it to an object literal.
- gabordemooij 15y agoYes it is, because you can not add them in the function body: cls = function(){} cls.staticMethod = function(){} vs cls = { staticMethod:function(){} } I prefer the latter because the static method can be defined within the body of the 'class' definition. Using the former method it's too easy to add static methods in different places.
- sktrdie 15y agoThere are so many wrong things about this article, I don't even know where to start. * Every time you call createNew(), all the methods and all the properties are re-allocated. This is bad for performance and memory consumption. This is why properties and methods should be added to the "prototype" of an object, so that they don't get re-allocated every time you want to create an instance. * The inheritance example is not actually inheritance but composition. They are two separate things: http://www.artima.com/designtechniques/compoinh.html http://www.artima.com/designtechniques/compoinh.html * Stuffing everything inside a createNew() function is not minimalist, it's just bad code. * It refers to "this", "new" and "prototype" as "confusing JS stuff". This obviously means he/she doesn't know anything about the JavaScript programming language. * JavaScript provides a basic keyword called "new" that easily lets you create a new object. Changing the API naming convention to something called "createNew", is bad practice and will confuse developers trying to use your code. Stick with "new". If you write code this way, not only it will quickly become slow, but it will also become hard to have other developers contribute to your code base because of the weird conventions. If you want to write real minimalist JS code, try reading Eloquent JavaScript instead: http://eloquentjavascript.net/ http://eloquentjavascript.net/
- TazeTSchnitzel 15y agoBy not using "new" they aren't changing the API naming convention. They're just not using the traditional OOP model. If you don't use new, you can pass down secrets and properties and compose an object in multiple layers.
- sktrdie 15y agoWhat do you mean by "If you don't use new, you can compose an object in multiple layers"? If you want to compose objects the correct way using prototypes, then you need to use new at some level. If you don't use it, then you're re-allocating the entire object's properties and methods every time you need to use it. You can do it as Crockford does with his "beget object" abstraction: http://javascript.crockford.com/prototypal.html http://javascript.crockford.com/prototypal.html But you still need to use "new". And personally, I'm not that convinced about promoting these sorts of abstractions as Crockford does. It's just really small syntax sugar around "new" and it's totally subjective. So most of the time I simply feel more comfortable using "new".
- gabordemooij 15y agoI dont use new, prototype and this because I find them confusing. While it may be trendy and cool to claim that this is just me being stupid and you being smart I have seen many disasters happen by people who claim to 'fully understand' Javascript. At least this method is clean and maintainable. Why use language constructs that you don't need? I really dont understand why prototypes and new-keywords would improve Javascript code. I try to write software that's free of bugs, software that can be trusted. Simplicity seems a logical strategy. Unfortunately almost every language today is bloated with features, why can't we have a minimal language, just like C? I have explained my point of view more extensively here: http://www.gabordemooij.com/articles/fatjs.html http://www.gabordemooij.com/articles/fatjs.html
- TazeTSchnitzel 15y agoWhilst I personally don't like using constructors and prototypal inheritance, I think it would be best if you try to understand something before dismissing it. Edit: Just because you don't understand something or refuse to understand it does not mean you should dismiss it.
- gabordemooij 15y agoWhy do you assume I don't understand prototypical inheritance? To me this highlights part of the problem of our community. Once you choose not to use a certain feature you are being regarded as stupid. What ever happened to the KISS principle? http://en.wikipedia.org/wiki/KISS_principle http://en.wikipedia.org/wiki/KISS_principle The minimal approach is simpler. Try explaining prototype OOP and minimal OOP to a newcomer and see for yourself. Software complexity is a result of evolution; as the code base grows it becomes more complex, there is no need for us to add it beforehand.
- stephenr 15y agoSimpler isn't always better. If your entire team is entry level developers who think jquery is magic, maybe you have a point, but frankly I'd rather work alone that with people that dense.
- tszming 15y agoI would recommend the doc from Mozilla (also minimalist): https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript https://developer.mozilla.org/en/Introduction_to_Object-Orie...
- mistercow 15y ago> no this, no new, no prototype. Therefore this approach is not only easy, minimalist and elegant but it also works in the most ancient and exotic browsers. You mean ones with broken JS implementations?
- gabordemooij 15y agoYes, it might help you in daily work environments.
- stephenr 15y agowhat "daily work environment" are you expecting people to have, that is browser based, and supports javascript, but doesn't support Prototypes, the new operator or "this"???
- mistercow 15y agoI get your jab about all JS implementations being somewhat broken (what complex system isn't?), but there's "broken", and then there's "broken to the point of not supporting core language features".