Syntactic difference between classes and constructor functions in Javascript?

Asked

Viewed 104 times

2

I’m studying Javascript and I noticed that, in the constructor functions, we can declare variables and constants. For example:

function Teste() {
  const nome = 'Bruno';
  this.nomeAtributo = nome;
}

console.log((new Teste()).nomeAtributo);

Above, I declared the constant nome and assigns its value to the property nomeAtributo.

Already in the classes, I noticed that this same behavior is not possible. If I try to declare constants and variables in the class body (outside the method block), I get a syntax error. In principle within the scope of the classes it is only possible to declare methods and properties. That’s right?

I tried to find a text that confirmed this, but I couldn’t find.

  • 2

    It’s a language syntax thing. You cannot use, for example, the statement const inside the "block" of a class and expect it to work, since it is not part of the grammar rules of the language. As for the class vs. function constructor semantics, it is the same thing, based on "prototypical heritage", which has already been answered in other questions here on the site.

3 answers

3


It is often mistakenly thought that all that is delimited by keys ({ and }) is a block. And that’s not always the case.

Obviously it does not apply to literal objects, which also use the keys to denote their syntax.

The keys that follow class are also not a "block" itself, since blocks, in accordance with the documentation:

A block (or compound statement in other languages) is used to group zero or more statements. The block is bounded by a pair of keys.

And for the class, the keys delimit the class body (not to be confused with block) which, according to the language syntax, contains a "list of class elements", which in turn may be the definition of a method or the definition of a static method.

Therefore, according to the syntactic rules of the language:

  • A block may contain a set of whichever language statement (such as statements if, const, for, while, etc.).
  • The body of a class may contain only definitions of methods.

Please note that upon approval of class Fields Proposal, the "list of class elements" will expand to also accommodate estates, so that it will be possible to declare, in the body of a class, methods and properties directly.


So, to answer your question:

  • Syntactically speaking, classes and constructor functions are different to the point that classes delimit the class body (which can define methods), while constructing functions delimit the block of a function (which may contain any kind of declaration).

So this doesn’t work:

class Foo {
  const bar = 'baz';
}

In view of the fact that const denotes a statement, which is invalid within the body of a class.

You could, however, declare a method (analogously to the constructor function would be the method constructor) which, in turn, could contain the variable declaration.

This is all a bit of Javascript syntax. In this sense, you can only do what is described by the language syntax. It’s the same thing as making one while for if and hope it works.

So, following the syntactic norms... This code:

function Teste() {
  const nome = 'Bruno';
  this.nomeAtributo = nome;
}

Written with the syntax class gets like this:

class Teste {
  constructor() {
    const nome = 'Bruno';
    this.nomeAtributo = nome;
  }
}

Apart from the syntactic difference, as said in the comments, there’s not much semantic difference, seeing as classes and construction functions operate on the same prototypical model.

2

A construction function is still a function like any other, which can have whichever valid code, not only constant declaration. For example:

function Teste(x, y) {
    // posso ter código "normal" que qualquer função teria
    const result = Math.pow(x, y);
    if (result >= 0)
        this.nomeAtributo = result;
    else this.nomeAtributo = result * -2;
}

console.log((new Teste(2, 3)).nomeAtributo); // 8

What happens is that, at some point, within the constructor function, it arrow the attributes of the this with some value. But nothing prevents it from having other "normal" code snippets, which do anything that is allowed within a function. See in the example above, I declare a variable result, do accounts, if, etc, and at some point I Seto this.nomeAtributo. The fact of being a constructor function does not exclude the possibility of terms code "extra", which is perfectly valid.

So when did you declare const nome within the function, only created a local variable to the function (a variable that exists only within the function, but that nay will be a class attribute). So much so that if you try to access (new Teste(2, 3)).nome, the result will be undefined.

That is, this const nome that you created has nothing special, is just a code like any other, which is perfectly valid within a function (whether it construction or not).


The equivalent of the above function, using class, would take all the function code and put in the constructor:

class Teste {
    constructor(x, y) {
        const result = Math.pow(x, y);
        if (result >= 0)
            this.nomeAtributo = result;
        else
            this.nomeAtributo = result * -2;
    }
}

console.log((new Teste(2, 3)).nomeAtributo); // 8

Note that in this case the attribute was not created either result. This is a local variable to the constructor (just as it was local to the function in the previous example), it exists only inside and has no relation to the class. So much so that if I try to access (new Teste(2, 3)).result, the result will be undefined.


Using your example, it would be the same as doing this:

class Teste {
    constructor() {
        const nome = 'Bruno';
        this.nomeAtributo = nome;
    }
}

console.log((new Teste(2, 3)).nomeAtributo); // Bruno

That is, the variable const nome is local to the constructor (which is still a function, and therefore may have any valid code within it, including declaration of local variables).

When you said you tried to do it like this:

class Teste {
    const nome = "abc"
}

This gives error because the language defined that this cannot be done (see here and here). In the body of a class (currently) can only have methods or declarations of static fields.


Obs: there is at the moment a proposal experimental to allow something like with this, but without the const:

// atenção, ainda é experimental, pode não funcionar em todos os ambientes
class Teste {
    campoPublico = 1;
    #campoPrivado = 2;
}
var t = new Teste();
console.log(t.campoPublico); // 1
console.log(t.campoPrivado); // undefined (campo privado não pode ser acessado)

Since it’s experimental, it might not work in all environments (I tested it on Chrome 90 and Node 14 and it worked). But anyway, this is what will still be allowed, but note that there is no const.


Further reading:

-1

Browser other questions tagged

You are not signed in. Login or sign up in order to post.