1

I was going to start using the Discord.js library to create a bot, but came across this first line of code:

const Discord = require('discord.js');
const client = new Discord.Client();

I was then curious to see how we could call the class without parentheses and call what almost looks like a static method... So i went about trying to recreate an example of how I might try to use something like this.

What I tried:

//this worked! but why?
class Discord{
  constructor(){
  }
}

Discord.Client = function(){
  console.log('this is client in a static method?')
}
new Discord.Client() //i could call the class using the key word 'new' and call the client static method. console.log --> this is client in a static method?

but then when i tried something like this and could not call class with new:

class Discord{
  constructor(){

  }
  static Client(){
    console.log('client static method')
  }
}
new Discord.Client()//Uncaught TypeError: Discord.Client is not a constructor
Discord.Client()//console.log --> client static method

I'm trying to understand what the difference is between the two, and please correct me if I'm wrong on any of this.

Thank you for taking the time to read this. Your help is greatly appreciated!!

Jcorral94
  • 51
  • 4
  • 1
    `Discord` is not a `class`. `Discord` is all the stuff that `discord.js` exports. `Client` is one of those exports. `Client` is a class. [https://github.com/discordjs/discord.js/blob/master/src/client/Client.js](https://github.com/discordjs/discord.js/blob/master/src/client/Client.js) – crashmstr May 27 '20 at 21:40
  • Got it! Makes sense now. Thank you! – Jcorral94 May 27 '20 at 21:41
  • Read up on the [javascript `new` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new). Most functions in javascript are also valid constructors, but not all; [the answers to this question](https://stackoverflow.com/questions/40922531/how-to-check-if-a-javascript-function-is-a-constructor) describe the exact cases in which a function can be used as a constructor and in which it can not. Functions declared with the `function` keyword are always valid constructors (as in your first case), but class methods (static or instance) never are (as in your second). – CRice May 27 '20 at 21:44
  • Thank you @CRice That helps clarify those examples. I will definitely take a read on the new operator. – Jcorral94 May 27 '20 at 21:50

1 Answers1

2

call the class without parentheses

Discord isn’t a class, although what a variable contains doesn’t make a difference as to whether you can refer to its value instead of calling it (or using it as a constructor) with parentheses. You can give any variable an uppercase name:

const Discord = 2;

and the actual value is defined like this (i.e. it’s just an Object, created with an object literal):

class Client {}

const Discord = {
    Client: Client,
};

With that out of the way, on to the difference in your question. Function expressions and declarations in JavaScript create functions that can be used as constructors:

function Foo() {}
new Foo()  // evaluates to a Foo instance
const obj = {
    Foo: function () {},
};
new obj.Foo()  // same idea
const obj = {};  // or class obj {}, or anything else that can get new properties
obj.Foo = function () {};
new obj.Foo()  // again

But every other type of function (except for classes) can’t, including:

  • arrow functions

    const Foo = () => {};
    new Foo()  // fails
    
  • method syntax functions

    const obj = {
        Foo() {},
    };
    
    class Bar {
        foo() {}
        static StaticFoo() {}
    };
    
    const barInstance = new Bar();
    
    // all fail
    new Foo()
    new barInstance.foo()
    new Bar.StaticFoo()  // as you’ve seen
    
  • generator functions

    function* Foo() {}
    new Foo()  // fails
    
  • async functions

    async function Foo() {}
    new Foo()  // fails
    

With class field support, which is somewhat thin but developing, you can write what you wanted inside the class declaration like this, with a function that isn’t a method-syntax function:

class Discord {
    static Client = function () {
        console.log('client static function');
    };
}

or with a class:

class Discord {
    static Client = class {
        constructor() {
            console.log('client static function');
        }
    };
}

Or, very short version: the static method syntax creates a different type of function than a normal function expression. Its differences rarely show up in practice, but use as a constructor is one of them.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • Thank you for the great examples and details! I went through the discord script files and can see how it is applied with your examples. :) – Jcorral94 May 27 '20 at 21:54