New-less JavaScript (2013)
jfire.io
jfire.io
This seems like a problem the language should solve incrementally. Especially with ES6 classes and modules!
How are we going to keep pushing the boundaries then? Had JS started with that sentiment, we would have a V8 JS runtime running about 100th the speed it does now for general purpose code, written with the aim of being as clear and reusable as possible.
Personally I prefer good, clear and concise code, over code written trying to appease some secondary affects on the inside of a black box which is not guaranteed to stay the same.
This is clearly an optimization, and I'm not saying all optimization is bad per se, but all optimization should be justified if it affects code-clarity. Are you sure these optimizations are warranted? Have you profiled your code and identified that this is a bottleneck for performance-critical sections of your code?
A former Nvidia-engineer had a really good rant about what sort of things your thinking leads to:
http://www.gamedev.net/topic/666419-what-are-your-opinions-o...
Key quote: "So the game is guessing what the driver is doing, the driver is guessing what the game is doing, and the whole mess could be avoided if the drivers just wouldn't work so hard trying to protect us."
I agree it's not a direct analogue, but the same line of thinking still applies.
Yes, we are all in the same game as GL driver developers and game devs, and that goes for all language implementations. The fine details of what gets optimised best may change from VM to VM, and from release to release, but it's important to understand the general assumptions that these systems are built around, because they don't change quickly.
In general dynamic languages that allow properties to be created and deleted on individual objects are a complete PITA to optimise, and more generally mutability of classes makes stuff harder, so in general even though you have these abilities in JS and other languages your code will often perform better if you limit your use of them, especially in areas where performance is critical. This doesn't mean you shouldn't use those mutability features, but you should have some notion of the cost you might be incurring.
http://bertanguven.com/preventing-memory-leaks-in-javascript...
`delete obj[x]` removes not only the reference to the value but also the key which prevents other forms of memory leak.
> In quite a few discussions online about reclaiming memory in JavaScript, the delete keyword is brought up, as although it was supposed to be used for just removing keys from a map, some developers think you can force de-referencing using it. Avoid using delete if you can. In the below example, delete o.x does a lot more harm than good behind the scenes, as it changes o‘s hidden class and makes it a generic slow object.
Although it's from 3 years ago it looks decent. The comments below are even more interesting than the article.
[1] : http://www.smashingmagazine.com/2012/11/05/writing-fast-memo...
Let's examine CoffeeScript ( which is one of the most popular ) :
class Foo
constructor: -> return 'bar';
foo = new Foo();
will compile to : var Foo, foo;
Foo = (function() {
function Foo() {
return 'bar';
}
return Foo;
})();
foo = new Foo();
Which IMHO, follows the very best practices of javascript. Since JS is such a flexible language if you don't have any coding standards, your code could become hell and unmaintainable very quickly.I would advise not to use the proposed "New-less JS", because it breaks the general coding style guides that a lot of libraries use and yes it would be possible to write it that way, but keep in mind that your code would be one step less readable from random developers.
The JS VMs tend to kind of finnicky and optimized towards certain types of idiomatic Javascript and it's my guess that the further off the common path you stray, the more likely you are to hit performance gotchas.
Your best bet is to transpile code that looks much like the benchmark suites they run. :)
In any case, why I mentioned preprocessors is that there is a lot of history behind every feature. As of this there are a couple of github issues [1] that explain why this approach has been used.
For the performance. Seems that "new" is way faster. [2]
[1] : https://github.com/jashkenas/coffeescript/issues/912 [2] : https://jsperf.com/obj-create-vs-new/4
Of course when I work in a team or on a big project I don't even consider it, because of future developers and the Bus factor.
They are? Delete maybe, due to language symantics - but not new. I think it's unfair to bundle them together in terms of newbie confusion.
Also every time I see one of these type of blog post, discussions in a book the work arounds are even worse.
JS is easy to understand, by the time you need 'new' it is not that difficult an extension of your current knowledge. As far as 'delete' even an advanced JS developer could go a year without calling it
Even I have to refresh my memory on these ambiguous parts of the language from time to time.
The author probably never used Smalltalk, just to cite one of the oldest dynamic languages.
btn := Button new.So can we just agree that many religions are nice. It's OK to try and convert people, but it's Not OK to force someone by changing the language itself.
With that said, I'm a bit worried about more and more religions entering the JS language. Like classes and block scope (ES6). And how some, both good and bad new features are forever changing the language.
So many headaches are to be had if you're not careful and using some decent functional things.
Absolutely. My preference for new modules is to use both newless and "this"-less Javascript. Newless via the technique outlined in this post (or encapsulated in a module: https://github.com/Mr0grog/newless), and this-less via the module pattern (see link in post).
This is the pattern followed by D3. It's easy to follow internally, gives you true private data and methods, and (IMHO) is a nicer interface for API consumers -- no `new`, `delete`, or `bind`'s necessary.
[1,2,3].map(User) [1, 2, 3].map(id => User(id))
[1] http://speakingjs.com/es5/ch15.html#_pitfall_unexpected_opti... [1,2,3].map(unary(User))
[[1,2],[3,4],[5,6]].map(apply(User)) [1,2,3].map( function(i) { return new User(i); } );
might seem more reasonable in the JS world.raganwald books cover this way of using javascript https://leanpub.com/u/raganwald
That being said, JavaScript is a powerful tool, if wielded correctly. It's so flexible. In a lot of ways, it's like a pizza. One man orders a pizza with anchovies, another with green peppers. And on and on. Eventually it's like they've got two completely different dinners.
I have tried to read code that was translated to Javascript using some source-to-source compilers and they are very hard to understand. On the other hand for a language like C, it is very easy to understand the output ( assembly ). Don't get me wrong, understanding the intricacies of assembly for each processor architecture is a difficult process, but the rules that define assembly language itself are not so, there is an opcode and some operands and each instruction performs an action on the operands or stored state in various registers. Javascript ( at least for me ) is too high-level to attempt to read a machine translated output. Programmers need to know at least one level below the abstraction to which they are programming to.