Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between prototype-based class syntax and class syntax in JavaScript?

Are these interchangeable syntaxes to create a JS class? I'm used to the class syntax but don't understand the differences between them exactly.

function User(name) {
  this.name = name;
}

User.prototype.sayHi = function() {
  alert(this.name);
}

let user = new User("John");
user.sayHi();

vs.

class User {

 constructor(name) {
   this.name = name;
 }

 sayHi() {
   alert(this.name);
 }

}

let user = new User("John");
user.sayHi();
like image 403
Lionel Yang Avatar asked Apr 04 '18 05:04

Lionel Yang


People also ask

What is class syntax in JavaScript?

In object-oriented programming, a class is an extensible program-code-template for creating objects, providing initial values for state (member variables) and implementations of behavior (member functions or methods). Wikipedia.

Is JavaScript prototype-based or class-based?

Unlike most other languages, JavaScript's object system is based on prototypes, not classes. Unfortunately, most JavaScript developers don't understand JavaScript's object system, or how to put it to best use.

What is the difference between prototype and object in JavaScript?

Every object in JavaScript has a built-in property, which is called its prototype. The prototype is itself an object, so the prototype will have its own prototype, making what's called a prototype chain. The chain ends when we reach a prototype that has null for its own prototype.

What is prototype-based in JavaScript?

Prototype-based programming is a style of object-oriented programming in which classes are not explicitly defined, but rather derived by adding properties and methods to an instance of another class or, less frequently, adding them to an empty object.


1 Answers

The main differences between classes and constructor functions are:

  • Classes can’t be called without new, but functions intended as constructors can (and their this will be wrong)

    'use strict';
    
    function Foo() {
        console.log(this);
    }
    
    class Bar {
        constructor() {
            console.log(this);
        }
    }
    
    Foo();
    Bar();
  • Classes can extend more types than constructors can (like functions and arrays)

    'use strict';
    
    function Foo(body) {
        Function.call(this, body);
    }
    
    Object.setPrototypeOf(Foo, Function);
    Foo.prototype = Object.create(Function.prototype);
    
    class Bar extends Function {}
    
    (new Bar('console.log(1)'))();
    (new Foo('console.log(1)'))();
  • Classes’ prototypes are their parents (they inherit static properties); writers of constructor functions usually don’t bother with this

  • Non-classes can’t extend classes (because they can’t call the parent constructor – see the first point)

    'use strict';
    
    class Bar extends Function {}
    
    function Foo() {
        Bar.call(this);
    }
    
    Object.setPrototypeOf(Foo, Bar);
    Foo.prototype = Object.create(Bar.prototype);
    
    void new Foo();

Classes are also scoped like let/const (block scope, temporal dead zone, not redeclareable) rather than like var (function scope, hoisted) or like function declarations (it’s complicated).

In your example, an additional difference is that sayHi is defined by assigning to a new property instead of with e.g. Object.defineProperty, so the property’s properties differ from those in the class example in that sayHi is enumerable in the former but not the latter.

function UserA(name) {
    this.name = name;
}

UserA.prototype.sayHi = function () {
    alert(this.name);
};

class UserB {
    constructor(name) {
        this.name = name;
    }

    sayHi() {
        alert(this.name);
    }
}

let a = [];
let b = [];

for (let key in new UserA()) a.push(key);
for (let key in new UserB()) b.push(key);

console.log(a, b);
like image 136
Ry- Avatar answered Sep 18 '22 12:09

Ry-