Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Understanding JavaScript Objects (halolabs.io)
84 points by octosphere on July 27, 2018 | hide | past | favorite | 27 comments


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.


He also uses `_proto_` (should be `__proto__`), `(‘b’, ‘c’)` (should be `('b', 'c')`) etc. in the inner text.


It looks like that's just an error. "Object" in uppercase is a special global variable in JS, but there's nothing special about "object" lowercase.


Thanks for the comment, appreciate it! Sorry for the typo, fixed now.


Is the prototype chain an example of an object as well? An object doesn't need to be instantiated as any sort of class, it can be a function?


Functions are indeed objects in JS, however:

'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.


just a synthetic sugar

'syntactic[al] sugar' is the term used for this sort of thing and JS classes in particular, just about everywhere.


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.


Can you rephrase? The "prototype chain" refers to the whole sequence of objects that link to each other by the `__proto__` property, e.g.:

    let vertebrate = {hasSpine: true},
        mammal = {hasHair: true},
        dog = {sound: 'bark'};
        sparky = {name: 'Sparky'},
        jumbo = {name: 'Jumbo'};
    
    mammal.__proto__ = vertebrate;
    dog.__proto__ = mammal;
    sparky.__proto__ = dog;
    jumbo.__proto__ = dog;
    
    console.log(sparky.hasSpine); // true
    console.log(jumbo.hasHair);   // true
    console.log(sparky.sound);    // 'bark'
    console.log(jumbo.name);      // 'Jumbo'
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?


To clarify I meant this example:

  var cons = function () {
     this.a = 1;
     this.b = 2;
  }
  var obj = new cons(); 
 
  cons.prototype.b = 3;
  cons.prototype.c = 4;
Was just confused as it seems to be applying class concepts to a function.


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.

Hopefully that all made sense!


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!


Yes it did. Thank you!


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).


What's with the giant photo of a hipster starter kit at the top of the article?


I think it means that like JS Objects, two hipsters are never equal, even if they have the exact same properties.


Probably a subtle nod to objects, as in, these are the objects you need to be a hipster.


As someone who hates working on a laptop, it's sad to learn that this will prevent me from being a hipster.


I suggest meta-hipsterism... being too hip to actually, you know, be a hipster. How dull that would be.


That would probably make me feel misunderstood all the time.


Hating things that others find convenient and practical actually does the opposite.


You win. I'm dying




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: