3

Given my code

const express = require("express")
const app = express()


console.log(typeof app)
console.log(typeof express)

My terminal tells me that both of these variables are functions!

This makes no sense to me because I can access properties from each of them as if they were objects and yet when I do a typeof in console.log my terminal tells me they are both functions.

Can someone please explain to me what these variables are and why its possible to access their properties as if they were objects?

Vishwanath
  • 6,284
  • 4
  • 38
  • 57
ooooohyesssss
  • 119
  • 1
  • 1
  • 7
  • In JavaScript, function can have properties too. Actually a function is also an object, a callable object. Ex. if you ever have used jQuery, you've written something like this: `$('...')` and also `$.ajax(...)`. – Teemu Jan 16 '20 at 06:34
  • 1
    Reading this https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions will help – Vishwanath Jan 16 '20 at 06:40
  • JavaScript functions are objects. – axiac Jan 16 '20 at 06:59

2 Answers2

1

According to the docs, The express() function is a top-level function exported by the express module.

It is similar like having Class and Object. The variable express that you are declaring is acting as a class, while the variable app is the object of it which is used.

Muhammad Zeeshan
  • 4,608
  • 4
  • 15
  • 41
1

when I require “express” I need to know if its an object or function

It's both. Functions in Javascript are objects.

Without getting technical, express is a factory function that creates an app instance and app is an express instance. Now, technically, both express and app are functions. But, functions in Javascript are objects and can have properties. The express object has static properties. The app object behaves much like an instance of the express class. It has both methods and instance data.

Now, getting a little more technical...

const express = require('express') gets you a function and that function is also an object and has properties.

This specific function is a factory function that creates an app object when you call it that is also a function that has properties.

So, express also has properties that can be used such as:

express.static
express.json
express.urlencoded

And, it can be called as in:

const app = express();

Likewise, app is a function that has properties too. It can be used as a function as in:

const server = http.createServer(app);
server.listen(80);

Or, it can be used like an object as in:

const server = app.listen(80);

If you output this:

console.log(typeof express);
console.log(typeof app);

You will see this:

function
function

They are both functions. But, functions in Javascript are objects too and can have properties.

So, you can do things like this:

function myFunction() {
    return "ok";
}

myFunction.greeting = "Hello";

console.log(myFunction());                 // "ok"
console.log(myFunction.greeting);         // "Hello"

Looking further at both express and app, if you did this:

console.log(Object.getOwnPropertyNames(express));

You would get this:

[
  'length',         'name',
  'prototype',      'application',
  'request',        'response',
  'Route',          'Router',
  'json',           'query',
  'raw',            'static',
  'text',           'urlencoded',
  'bodyParser',     'compress',
  'cookieSession',  'session',
  'logger',         'cookieParser',
  'favicon',        'responseTime',
  'errorHandler',   'timeout',
  'methodOverride', 'vhost',
  'csrf',           'directory',
  'limit',          'multipart',
  'staticCache'
]

And, this:

console.log(Object.getOwnPropertyNames(app));

would get this:

[
  'length',          'name',            'prototype',
  'constructor',     '_events',         '_eventsCount',
  '_maxListeners',   'setMaxListeners', 'getMaxListeners',
  'emit',            'addListener',     'on',
  'prependListener', 'once',            'prependOnceListener',
  'removeListener',  'off',             'removeAllListeners',
  'listeners',       'rawListeners',    'listenerCount',
  'eventNames',      'init',            'defaultConfiguration',
  'lazyrouter',      'handle',          'use',
  'route',           'engine',          'param',
  'set',             'path',            'enabled',
  'disabled',        'enable',          'disable',
  'acl',             'bind',            'checkout',
  'connect',         'copy',            'delete',
  'get',             'head',            'link',
  'lock',            'm-search',        'merge',
  'mkactivity',      'mkcalendar',      'mkcol',
  'move',            'notify',          'options',
  'patch',           'post',            'propfind',
  'proppatch',       'purge',           'put',
  'rebind',          'report',          'search',
  'source',          'subscribe',       'trace',
  'unbind',          'unlink',          'unlock',
  'unsubscribe',     'all',             'del',
  'render',          'listen',          'request',
  'response',        'cache',           'engines',
  'settings',        'locals',          'mountpath',
  'router'
]

So, you can see they each have a lot of properties in addition to being functions.


Ok please tell me if I have got this correct. 1) When I do this… const express = require(“express”) I store a “Class” into the express variable. 2) Then when I do this… express.json() I am accessing the json() function inside the express class ?

As I said in my answer above that express variable represents a factory function. That's a function that, when called, creates an object for you. It's a different way of creating an object from directly calling a constructor as in new myObj(). express.json is a function that, when called, creates a middleware function for you that uses the parameters you passed the function.

The Express architecture differs a bit from a pure class style architecture. It uses a factory function that creates an instance (essentially of a class). And, then the app represents that instance, but also works as a request handler on its own.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Ok please tell me if I have got this correct. 1) When I do this… const express = require(“express”) I store a “Class” into the express variable. 2) Then when I do this… express.jason() I am accessing the jason() function inside the express class ? – ooooohyesssss Jan 16 '20 at 21:37
  • @ooooohyesssss - As I said in my answer that `express` variable represents a [factory function](https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)). That's a function that, when called, creates an object for you. It's a different way of creating an object from directly calling a constructor as in `new myObj()`. `express.json` is a function that, when called, creates a middleware function for you that uses the parameters you passed the function. The Express architecture differs a bit from a pure `class` style architecture. – jfriend00 Jan 16 '20 at 22:10
  • But when I import this "factory function" into the app.js document, I am able to immediately access functions inside it without even calling it as shown. const express = require("express"); express.json(); By virtue of this simple code, require("express"), am I invoking its factory function? – ooooohyesssss Jan 16 '20 at 22:47
  • @ooooohyesssss - No. `require('express')` returns the factory function. That factory function also contains some static methods such as `express.json()`, but those are of little use until you create an `app` instance by calling the factory function. Your `express` variable is analagous to a class (but you create an instance of the class by calling it instead of using `new`). `express.json()` is like a static method of a class. – jfriend00 Jan 16 '20 at 22:50
  • @ooooohyesssss - This part of Express is a bit of a screwy design (my opinion). They apparently wanted to do everything by only exporting one top level symbol `express` which meant they had to cram several other things into it that might normally be done in a little more common way. It's not hard to use, once you understand, just not as conventional to understand. – jfriend00 Jan 16 '20 at 22:52
  • @ooooohyesssss - FYI, I've added more of this discussion to the end of my answer. – jfriend00 Jan 16 '20 at 22:53
  • Hey everyone I really do appreciate your help here. I'm very new so please bare with me. Can someone please make up a simple example of how to create a "factory function" that returns another function? – ooooohyesssss Jan 16 '20 at 23:08
  • @ooooohyesssss - A [Google search for "factory function Javascript"](https://www.google.com/search?q=factory+function+in+javascript) will show you lots of good articles with lots of examples. Here's [one article](https://medium.com/javascript-scene/javascript-factory-functions-with-es6-4d224591a8b1). It's basically any function that returns a new object. – jfriend00 Jan 16 '20 at 23:11
  • @ooooohyesssss - Can also see [Constructor function vs. factory function](https://stackoverflow.com/questions/8698726/constructor-function-vs-factory-functions). – jfriend00 Jan 16 '20 at 23:13
  • @ooooohyesssss - One very good use for factory functions is described [here](https://stackoverflow.com/questions/49905178/asynchronous-operations-in-constructor/49906064#49906064) when you have asynchronous operations involved in the creation of the object and a regular constructor doesn't quite work properly. – jfriend00 Jan 16 '20 at 23:16
  • whats confusing me is that when I do this code, const express = require("express"), it looks as though the factory function inside the express variable has already been invoked because you are able to access functions from it like so, express.json(). How can these properties be accessed if the factory function inside the variable express hasnt been invoked yet? – ooooohyesssss Jan 16 '20 at 23:39
  • @ooooohyesssss - The designers of Express could have just as easily exported a single object with these properties on it `{express, json, urlencoded, Router, raw, static, text}` and let you call them from that exported object. But, instead, they decided to export only one function (express) and put all the other static functions on it as properties. It's just a different way of exporting a bunch of plain functions. – jfriend00 Jan 16 '20 at 23:58
  • if the designers of express exported the properties on it then when I console log type of on the express variable it should say object not function. As I understand it, static methods can only be used in classes not functions so if you say that the express valiable is a function factory I dont understand how properties inside it could be static. – ooooohyesssss Jan 17 '20 at 00:25
  • @ooooohyesssss - Functions are objects in Javascript (I think I've said that multiple times now). So a function can be called as a function AND have properties. `typeof express === "function"`, but it can also have properties because a function is also an object. My answer says this 6 times. Please read again. A function in Javascript derives from object, therefore is has both the capabilities of a function AND the capabilities of an object. – jfriend00 Jan 17 '20 at 00:57
  • @ooooohyesssss - Also look at the `myFunction` code example in my answer. That illustrates how functions can also have properties. Again, I'm feeling like you aren't reading my answer where I attempted to explain all this. – jfriend00 Jan 17 '20 at 00:58