It's always nice to find this kind of article where the author synthesizes a lot of knowledge in a single place.
I just have an advice, please don't mix upper case and lower case for programming names in your text, it makes it a little harder to understand, as a reader I was not sure if the author was talking about the same object/function or not. For instance I could find "object.assign()" inside a paragraph but then "Object.assign()" in the code example.
'function' === typeof (function(){}) while
'object' === typeof ({})
There are no classes in JavaScript, the way there are in some OO languages.
The new syntax of 'class' introduced in ES6 is just a synthetic sugar which will be translated to an Object and would use inheritance via the prototype chain.
I suggest the book 'JavaScript: The good parts' (by Douglas Crockford) for more on this topic.
Thanks, I'll take a look! I've been in industry a couple of years now, but my experience with JavaScript has largely been "hit it until it works and then don't touch it again" - there seems to be at least two ways to do anything with no way to tell if one is objectively better.
Well, that’s because due to compatibility we still have the old way of doing things alongside the new ways of doing things plus the multiple future-now way of doing things. JavaScript recently has been moving fast both from a community and committee perspective. However, I think is nowhere near as bad as C++ where you can do similar things is different ways with big nuances on end results.
I highly recommend "Eloquent Javascript" instead because it's easier for beginners or developers coming from another language. It's available online for free too.
When you access `sparky.hasSpine`, the JS engine first checks whether `sparky` has an "own property" called `hasSpine`. It doesn't, so it checks `sparky.__proto__.hasSpine`, which is the same as `dog.hasSpine`. No luck, so it checks `sparky.__proto__.__proto__.hasSpine` (i.e. `mammal.hasSpine`), and finally `sparky.__proto__.__proto__.__proto__.hasSpine` (i.e. `vertebrate.hasSpine`), which resolves to `true`.
This entire structure of objects linked through their `__proto__` property is what we call the "prototype chain". Does that answer your question?
Ah, I see. The special thing here is the `new` keyword. When an object is created using `new myconstructor()`, the following steps occur (among others):
1. create a new empty object; call it `newObj`
2. call the constructor using `newObj` as its `this` context, so that `this.a = 1` is effectively `newObj.a = 1`
3. if the constructor has a `prototype` property defined, invoke `newObj.__proto__ = myconstructor.prototype` to establish the prototype chain on the new object
The critical distinction here is between `constructor.prototype` and `object.__proto__`. For exactly this reason, it bothers me a bit that the article uses `Prototype`, with a capital "P", to mean "the thing that `object.__proto__` points to". This is completely different from the `prototype` (small "p") property of a constructor, which is essentially just a holding place for the `__proto__` property of any objects created by calling this constructor with the `new` keyword.
Note that constructorFunction.prototype predates __proto__ in the official specs (and also `class` notation) and is the oldest bit of object-oriented programming support in JS.
__proto__ on objects was originally a leaky abstraction in a specific browser. It caught on such that other browsers borrowed it, because they unfortunately had to, but the specs and the browsers all consider it deprecated and warn not to use it: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
(The standards compliant way to get an object's prototype at runtime is Object.getPrototypeOf(obj), and to change an object's prototype instance at runtime is Object.setPrototypeOf(obj, newPrototype).)
Very good points. And thanks for the note about Object.getPrototypeOf(obj) and Object.setPrototypeOf(obj, newPrototype), I don't think I had ever actually looked that up!
In JS, everything that's not a primitive is an object, and primitives can themselves be implicitly coerced to objects. That is to say, these are equivalent:
(new String("abc")).length
"abc".length
Functions are really just objects that can be invoked as a function, and they can have properties and even prototypes set the same as any other object. This used heavily in React:
function DivWrapper({ children }) {
return <div>{children}</div>
}
// show a nice name when debugging
DivWrapper.displayName = 'DivWrapper';
// verify incoming props when debugging
DivWrapper.props = {
children: PropTypes.node
};
The problem is that in the latter case the function object doesn't know what it's name is. This pattern gets unnecessarily abused just to be cool or follow the cargo cult.
React adopted displayName to avoid "the function object doesn't know its name" issues, as well as names being mangled by minifiers (or, in the future, stuff like WASM).
I just have an advice, please don't mix upper case and lower case for programming names in your text, it makes it a little harder to understand, as a reader I was not sure if the author was talking about the same object/function or not. For instance I could find "object.assign()" inside a paragraph but then "Object.assign()" in the code example.