Object-oriented Programming in vanilla JavaScript
medium.com
medium.com
For example:
> While this is often considered to be one of JavaScript's weaknesses, the prototypal inheritance model is in fact more powerful than the classic model. It is, for example, fairly trivial to build a classic model on top of a prototypal model.
Although the MDN content is CC-licensed it behoves the author to be clearer about what is quotation and what is original content.
[0]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inhe...
https://mikegerwitz.com/papers/coope/coope.pdf
I also provide a lot of information on the implementation of GNU ease.js here:
https://www.gnu.org/software/easejs/manual/Implementation-De...
https://gist.github.com/nomad-software/78be4f1dd429325c5ebed...
I would always start with this pattern for readability and maintainability sake and if performance becomes an issue switch to the `Obj.prototype.method = f()` form to avoid duplicating method instances.
https://developer.mozilla.org/nl/docs/Web/JavaScript/Inherit...
But note:
> The lookup time for properties that are high up on the prototype chain can have a negative impact on performance, and this may be significant in code where performance is critical. Additionally, trying to access nonexistent properties will always traverse the full prototype chain.
This makes no sense to me - surely every non-trivial JavaScript implementation has inline caching, and are not doing any kind of lookup at all in performance critical code?
The author is also trying to update it and is close to their funding goal: https://eloquentjavascript.net/3rd_edition/
Callback Heaven: Continuation Passing Style Patterns for JavaScript:
https://medium.com/@b.essiambre/continuation-passing-style-p...
If, for some reason, you need to support old browsers, you can transpile to ES5, ES3, stone tablets and similar.
var MyApp = MyApp || {};
This is an anti-pattern, only use it for polyfilling. Use local variable scope!It can definitely be overused, which is probably why it's an anti pattern, but it had it's uses before webpack.
"use strict";
if(window.hasOwnProperty("MyApp")) throw new Error("MyApp already exist!");
var MyApp = {};
But I recommend using a module loader. const foo = {
someVal: true,
methodA() {},
methodB() {}
};
const bar = Object.assign({}, foo, {
methodC() {}
});
// bar now has all the properties of foo, plus methodChttps://docs.microsoft.com/en-us/scripting/javascript/refere...
IE already requires twice the budget - no grid, no flex, no ES8, and maintaining polyfills for all these things (if they're possible) requires maintenance and slows down build time.
Even slow moving corporates have AD managed Chrome or Edge since half the products they purchase don't work with IE.
The only reason people keep supporting it is people keep making it a big deal if something doesn't work on an unmaintained browser. We have to draw the line somewhere.
Frontend is grid, flex, and ES8. Supporting the older equivalents is expensive and it's web developers, caught in a culture of "it's good to support outdated browsers" who are paying the cost themselves, not clients.
It takes double the amount of effort (a conservative estimate) for async.waterfall, endless .then() chaining, callback hell and various other techniques to work around lack of `await`
It takes double the amount of work (a conservative estimate) to do some kind of weird Flash thing because your browser doesn't support HTML5 clipboard.
...amongst a massive amount of other tech, all of which is supported on current browsers.
You don't see the cost since you're already paying it by avoiding current frontend techniques. But unless someone else is paying that cost you're giving away your time for free by supporting IE.
(Of course, you should support Edge amongst every other major browser)
For both the css and clipboard problems, there are loads of well known and supported libraries if supporting IE is in scope of your project.
Flex and grid are hard to emulate. So is clipboard.
That said, whenever I teach OOP in JS I have found that a lot of developers do not understand the prototypal nature of JS.
Another source of confusion is the `this` keyword, how it works, and consequently how apply/call (which this article uses) affect `this' inside the function (or method).
[1] - http://looselytyped.com/blog/2012/08/22/on-prototypal-inheri...
1) if there are people who come back to using inheritance AFTER doing programming with typed systems that support typeclasses (like Haskell). If so, would you able to articulate why you think inheritance is still a superior pattern?
2) if there were any use cases that could be solved using inheritance that could not be solved more elegantly without it?
When you separate data from functionality into separate "things", composing things out of them becomes nicer.
I'm not a Haskell programmer, but AFAIK type classes contain functionality, NOT data (state).
Example of what I'm talking about: Clojure's Protocols.
Overloading not inheritance. It is closer to the notion of interfaces in traditional OO languages, but it's a mistake to confuse interface implementation as inheritance.
This is a common problem with traditional OO languages: they conflate inheritance with subtyping, ie. "Y inherits the behaviour of X" is not always the same as "Y can be used anywhere an X can be used" (subtyping). C++ has "private inheritance" to separate these notions now, but it's a kludge from this initial design mistake.
So type classes use subtyping, but not inheritance. Interface implementation is also closer to subtyping than inheritance.
There are behavior mixins, that you can look at Django views as an example. There are interface implementations when you want to have a few almost complete standard ones.
Both are cumbersome to implement on Haskell. If you make sure to not use any widely used class, you can hack them out of some sets of hierarchical type classes with possible some overlapping. But leaving half-done stuff at your API to be filled by client code is never pretty there.
> MyApp.users = MyApp.user || {};
Is this a typo, or intentional? If it is intentional, can someone explain the thought behind it?
Also, in some examples Medium (or the author's text editor) seems to have changed apostrophes and quotation marks, this makes the examples harder to try.
foo = foo || {}
"mark foo as being foo if it is already defined or as an empty new object {} if it is not"It's just to not accidentally set a already defined foo as an empty object incase foo is already defined. Yeah... JavaScript...
Another common idiom:
const PORT = process.env.PORT || 8080
The || (logical OR) can be used for setting a default incase the value before it is falsey (null, undefined, false...).For example, in Python:
>>> foo or "default"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined
In Javascript, variables are either bound (e.g. with `var`, as a function argument, etc.) or else they're treated as properties of the `window` object (behaving effectively as globals).This is very unusual, and can be thought of as mixing "data" with "code": the `window` object acts like a reified version of (global) binding environment, which in most other languages is implicit. This has implications for things like the usual distinction between bound and free variables (since we can imperatively add fields to `window` at any point), and hence for things like alpha-equivalence.
For some reason, the short-circuiting is more used on languages where undefined vars is in the same class of missing values. But that reason is not obvious to me. Python in particular has an odd mixing of quasi-static and dynamic errors that works unreasonably well but does not accept this construction.
Yes, but in that case the variable is irrelevant:
foo = None
foo or "default"
Here the variable `foo` is 'just doing its job' and can be simplified away to get: None or "default"
This shows that variables aren't involved here: `or` is just an operation on data (in this case `None` and `"default"`), just like `+` or ``.> It is just that undefined vars in Python are an error in a different class from a missing value.
Exactly, and I think that's a perfectly reasonable justifaction for disparaging Javascript (along with bash, PHP and anything else which has this similar behaviour).
In fact, as I said above, Javascript doesn't even have a notion of "undefined variable", since variables will be looked up in the `window` object if they're not locally bound, and hence what looks* like an undefined variable is actually (according to Javascript's semantics) a missing value (a missing property of the `window` object).
> Python in particular has an odd mixing of quasi-static and dynamic errors that works unreasonably well but does not accept this construction.
I'm not sure what you mean here. As far as I can tell, there are two ways to think about errors in Python:
- From one perspective, all Python errors are dynamic, since they happen at run time when we attempt to interpret the offending code. Some of these errors happen when/if we interpret an `import` statement, some happen when a more localised expression/statement is encountered.
- A different perspective is that Python doesn't actually have a concept of errors at all. There are values available in the language which are called "errors", but they're not really errors, in the same way that `myError = "hello"` isn't actually an error (it's a string, which might represent an error but it isn't a distinguished category of things; it's just a value). Since it's semantically meaningful to perform calculations involving these values (often, but not necessarily, with the control-flow statements `try`, `except` and `raise` (which is just another form of `yield`)) they're not "errors" in the same way that, say, a segfault or a compiler error is (which Python doesn't, or shouldn't, have).
For example, here's a perfectly valid (although inadvisable) way of defining `hello world` in Python:
$ cat x.py
def say_hello():
try:
foo()
print "goodbye"
except:
print "hello"
def foo():
i_am_undefined
$ python
Python 2.7.13 (default, Dec 17 2016, 20:05:07)
[GCC 5.4.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import x
>>> x.say_hello()
hello
>>>it's a typo
I really wish that class syntax did not become a thing in Javascript. IMO that was the biggest mistake made so far in it's development. Just call a spade a spade instead of piling another level of abstraction on top.
I don't have a problem with the class title, after all it describes a class of things. When you extend something you really extend the scope of your class, so I still find it adequate.
There are differences in OO behavior between Java and C# but I haven't heard people complaining about naming classes classes.
Classes are static contracts that define the state and behavior of object instances.
Javascript objects are not contractually obligated to have the state and behavior of a 'class'.
> Javascript objects are not contractually obligated to have the state and behavior of a 'class'.
I don't know what you mean by "contractually obligated", but if I instantiate a class in JS then it will have a state and behavior I defined in that class. If your problem is that if I change that class later, then the instances will change as well, then yes, it works like that. Calling something a class in my mind is not strictly limited to classical OO, it's just a loose concept different languages implement differently.