Real-World JavaScript Anti-Patterns
blog.javascripting.com
blog.javascripting.com
items.forEach(function(item) {
doSomething(item);
});
being an anti pattern. Many of these looping functions actually pass more than one argument to the callback, so writing items.forEach(doSomething);
will break if doSomething is a function with optional arguments. ['10','10','10','10','10'].map(parseInt)
// [10, NaN, 2, 3, 4] parseInt('10', {test: 'test'})
10
parseInt('10', 'test')
10
parseInt('10', '2')
2It's true that in many cases the shorter version would not be harmful, but I have been bitten by a somewhat similar case where I meant for for the callback to be called with no arguments. Since the callback was passed in the latter style, it was called with arguments and the undesired behavior was difficult to debug. Or rather, it would have been, except that I work with incredibly smart people who saw the problem almost instantly.
function only1(f) {
return function(x) {
return f(x);
};
}
then your example becomes: items.forEach(only1(doSomething));
Edit: just realized this is what "spots" in the blog post bahmutov linked to does (except spots is more flexible).Function.prototype.bind() makes sense, though.
"so one obvious improvement would be to use selectors instead of the execrable DOM API"
Additionally, DOM API is slow. Wrapping your access to the DOM in additional layers of abstraction isn't a win or "anti pattern". It's a maintenance trade off.
With React, since my "markup" and code is all just Javascript the common theme has become "How do I accomplish my goal in plain old Javascript?". The skills I've been picking up are definitely transferable to projects that don't use React or any other JS library.
Though I do keep forgetting to add `.bind(this)` all the time that it makes me miss using `var self = this;`.
As for writing things "the Angular way", it's about truly separating your MVC layers using two way databinding. I don't care how you do it as long as you keep V as declarative as possible. It sounds like "the javascript way" for you might just involve a lot of storing data in the DOM.
I think a much more robust pattern involves:
A Model - This is Javascript data stored outside the DOM, for easy manipulation. It is usually accessible via the window object
A ViewModel - This is Javascript data that is stored outsidd the DOM but is referenced directly by a data-bound component. It can involve view transformations such as time/date localization.
A View - This is the actual DOM component, in Angular it is a "directive". It reacts to changes in the ViewModel and can also change the Model (which in turn changes the ViewModel).
That way, for example, if you want to implement optimistic visual feedback you can do it in the Model and have the model try to sync or revert.
All this becomes even more complex when you have to build multi user apps. You can use Firebass or Parse etc. or you can check out http://platform.qbix.com -- open sourced but still a work in progress until 1.0
I don't think I've ever modified the DOM directly when using React. Try it out, it's a really refreshing take on building client-side apps.
React takes less opinions than Angular, thus leaving more for the user to determine how he/she wants to solve it. Fundamentally, React is more sound in that regard since it doesn't dominate everything as strongly - it is pretty clear that the Angular team agrees in this regard, and why they are moving to modularize everything in 2.0 (and why some formally core pieces such as the router were split off in 1.x).
Using either library helps with understanding of javascript and the browser - unless you contribute to/author angular components, React probably gives more precisely since it doesn't hide as much of the complexity. My own experience with Angular has been the deeper I delve into using it, the more I find myself moving towards using pure javascript in creating abstract classes while having the Angular-specific code be extensions of those classes - this pattern is transferable between frameworks/libraries, and likely an understated best practice when working in the browser.
function handleClick(i) {
this.innerHTML = i;
}
for (i = 0; i < elems.length; i++) {
elems[i].addEventListener("click", handleClick.bind(this, i));
}
In the for loop, the this value refers to the global object. To get the desired effect, it should be changed to elems[i] (this piece of code is trying to bind a handler to an element).That being said, I'm glad this forced me to look up _.partial - seems like you can pass '_' as a parameter and that position in the arguments will not be bound in the partial function!