Constructors and prototypes

Am I the only one who finds Javascript’s approach to constructors and prototypes kind of strange? I’m not really understanding why they’re not used the same way Java does it, which in my opinion is intuitive.

It is because JavaScript is a prototype language at its core. Once you get used to using prototypes and understand how they can improve your code (where needed), you will wish Java had them.

1 Like

Would you be willing to discuss this further on this thread? I’d be interested to hear the explanation of this assertion. I guess I don’t see how that’s better than Java’s constructors. These seem to do basically the same thing. It seems like in javascript you’re defining the constructor then a prototype separately, but in Java its one step. The section I’m on right now deals with inheritance, which is very straightforward in Java. In javascript its more confusing. I dont know why, but it is.

Don’t worry. Once you’ve learned all about prototypes, you can forget all about them and just use the class syntax. It’s now perfectly possible to do solid object-oriented programming in JavaScript without ugly syntax - even better in TypeScript though…

1 Like

To be fair, I wouldn’t call it prototypical “inheritance”

Kyle Simpson put it best by calling it “behavior delegation” : https://davidwalsh.name/javascript-objects

1 Like

Classes are just syntactic sugar around prototypes though

There are minor differences of course, but that doesn’t mean they correspond to classical OO.

You can fake it in the same ways of course, but it’s prototypes all the way down

This isn’t unique to JS FWIW, and even other prototypal based OO languages implement things differently (see for example delegation vs concatenation based prototypal OO):

1 Like

Constructors aren’t necessary in JS, they are only there to make the language look more like Java (this is literally why they exist). This may be the most confusing thing coming from Java.

As @DanStockham says it isn’t really classical inheritence, but you generally want it for the same purpose, to share. The way prototypal inheritance works :

  1. you have an object
  2. you would like an object like that but with some extra stuff.
  3. copy the object and add the extra stuff to it.

It’s lightweight and simple and powerful. Note that JS is a weakly typed dynamic language — objects can be modified at will, with no ceremony.

So, it sounds like I should stop thinking about classes and the hierarchy of class inheritance when I’m working with JS…

More lexical scoping I would say

1 Like

Yes I would strongly advise this when dealing with JS.

This is quite possibly going to make life harder for you if you try to write big applications using JS, particularly from a tooling PoV. IMO this isn’t a downside — personally I would say use something designed for writing big applications (like, say, Java) to do that — but YMMV.

Typescript lets you write stuff that looks and behaves very much like C#. It may be a lot more comfortable for you to use that, coming from Java. It now looks almost exactly like a classical OO language. However, it is still JavaScript, so actually writing it in the same style…not sure if that’s a good idea at all.

Step by step in which you provided makes it simple for those not in the know in how prototype works in JS. That step by step gave me great insight, and pretty much made my day!:love_you_gesture:

2 Likes

what step by step are you talking about? Do you mean about copying an object then adding any additional stuff you need? That sounds to me an awful lot like inheritance and adding new methods to the children.

Check previous message by DanCooper, there is a numbered list - I imagine it is that one

1 Like

@BitsInMyBlood
There’s a 1-3 step process that @DanCouper puts in place when it comes to prototypes.
This is what he put into perspective:

  1. you have an object
  2. you would like an object like that but with some extra stuff.
  3. copy the object and add the extra stuff to it.

I just thought the way he put it was pretty simplistic.

It is how inheritance is implemented in JS, yes. But I think what other people are getting at is that it is useful to kinda separate that model from how inheritence works in classical OO, trying to model directly how classical OO does inheritance tends to lead to v bad JS code. Prototypes are a much simpler model, but one that leans heavily on JS being a very loose dynamically typed language – it is effortless to add stuff to object. Note there are other similar languages – Scheme or Lua for example – where it is a common and almost trivially easy homework problem to implement prototypal OO.

1 Like

so, I want to think about JS more loosely and not think it terms of class hierarchy OO, just using prototypes when helpful?

Yes, I would say so. I mean you can do it the way you’re used to, the semantics in the language now look similar (this has downsides, but at least everything is a lot more consistent):

class Example {
  constructor(foo, bar) {
    // instance variables.
    this.foo = foo;
    this.bar = bar;
    // NOTE no private variables, convention is this:
    this._baz = "I should be private"
  }

  // equivalent of an instance method:
  method1() {
    // do stuff
  }

  // equivalent of a class method:
  static method2() {
    // do stuff
  }

  // Getters and setters:
  get baz() {
    return this._baz;
  }

  set baz(val) {
    this._baz = val;
  }
}

Inheritance:

class InheritedExample extends Example {
  constructor() {
    // access/call functions on the parent:
    super();
  }

  // overrides method on parent:
  method1() {
    // do stuff
  }

  // add more stuff
  method3() {
    // do stuff
  }
}

And the class properties proposal is likely to go through this year:

class Example2 {
  // If you don't need to pass in values on instantiation,
  // can just set properties directly on the class:
  foo = "foo";
  bar = "bar";
  // Private properties:
  #baz = "baz";

  method1() {
    return [this.foo, this.bar, this.#baz];
  }
}

BUT they still work exactly the same, this is all just sugar over the prototype model.

There’s a good argument to be made that you should avoid inheritence unless absolutely necessary in OO anyway (composition over inheritence), so this is maybe less of an issue than is might otherwise be. But whereas in Java et al, you have a very consistent way to write classes and create objects, in JS there are multiple ways, things tend to get messy quite fast. Scoping rules are a bit wierd. The dynamism and weak typing make it very easy to introduce issues by accident. The tooling is nothing like as good as for Java et al (static typing ftw), building class-based projects is quite difficult in comparison.

It’s very important w/r/t how JS works, but I’d maybe not think about it too hard. As I said in one of the other posts, you might get some joy out of using Typescript (typed layer over JS, and effectively can turn JS into much more of a recognisable OO language). The improvements it can make from a tooling PoV are fairly staggering if nothing else (project-wide refactoring for example). The type system is a wee bit complicated IMO (to deal with how JS works).

2 Likes