[comment]: # "markdown: { smartypants: true }" # Classless JavaScript AJ ONeal
[@\_beyondcode](https://twitter.com/@_beyondcode)
[twitch.tv/coolaj86](https://twitch.tv/coolaj86)
### a.k.a. _JavaScript as the good Crockford intended_
# TL;DR
```js var Person = module.exports; ``` ```js Person.create = function (p) { var person = { name: p.name || "Another Jane Doe", age: p.age || 0, }; person.creditCard = function () { return "****-****-****-" + p.creditCard.slice(-4); }; return person; }; ``` ```js Person.save = async function (p) { return await request({ url: `/api/person/${p.id}`, json: p, }); }; ```
> I made up the term 'object-oriented', and I can tell you I > didn't have C++ in mind > > \- Alan Kay, OOPSLA '97
### Newsflash JavaScript doesn't have classes.
Why would anyone _want_
to do classes in JavaScript?
## Benefits of JavaScript
## Benefits of JavaScript - Serializable
## Benefits of JavaScript - Serializable - Duck-Typed
## Benefits of JavaScript - Serializable - Duck-Typed - Closures
## Benefits of JavaScript - Serializable - Duck-Typed - Closures - Async
## Benefits of JavaScript - Serializable - Duck-Typed - Closures - Async Pretty much the same as Go and Rust.
## Serializable, Hydratable ```json5 { name: "John Doe", age: 37, } ``` JSON, APIs, Database
## Duct-Typed ```js // if is Promise-like if (o.then) { return await o; } return o; ``` Mix and match capabilities.
## Closures ```js function createApiRequester(key, secret) { return async function (data) { return await request({ auth: { user: key, pass: secret }, json: data, }); }; } ``` Composable, ad-hoc state.
```js Person.api = createApiRequester( "https://example.co", "my-user", "my-token" ); await Person.api("/api/person/1"); await person.api("/api/person/1", { name: "AJ" }); ```
## Async ```js await Promise.all([ // apiRequest(opts), fs.readFile(opts), ]); ``` Non-blocking event loop, without mutexes.
## Detriments of Classes - Awkward State (_this_-ness) - Inheritance - General Complexity Pretty much the same as C#, C++, and Java.
## Factories & Value Objects ```js var Person = module.exports; Person.create = function (p) { var person = { name: p.name || "Another Jane Doe", age: p.age || 0, }; // ... return person; }; ``` Plain-old functions & JSON.
## Static Methods ```js Person.greet = function (p, other) { return `Hello ${other.name}! I'm ${p.name}!`; }; ``` Attach functions at the package (factory) level.
## Member Methods ```js Person.create = function (p) { // ... person.greet = function (other) { return `Hello ${other.name}! I'm ${person.name}!`; }; // ... }; ```
## Member Methods ```js Person.create = function (p) { // ... person.greet = function (other) { return `Hello ${other.name}! I'm ${person.name}!`; }; // ... }; ``` Taints the object (too much like classes).
## Realistic Static Method ```js Person.save = async function (p) { return await request({ url: `/api/person/${p.id}`, json: p, }); }; ``` ```js await Person.save(p); ``` For "public" or "static" methods.
## Realistic Member Method ```js Person.create = function (p) { let cc = p.creditCard; p.creditCard = null; // ... }; ```
## Realistic Member Method ```js Person.create = function (p) { let cc = p.creditCard; p.creditCard = null; // ... }; ``` ```js person.creditCard = function (expose) { if (expose) { return cc; } return "****-****-****-" + cc.slice(-4); }; ```
## Realistic Member Method ```js Person.create = function (p) { let cc = p.creditCard; p.creditCard = null; // ... }; ``` ```js person.creditCard = function (expose) { if (expose) { return cc; } return "****-****-****-" + cc.slice(-4); }; ``` If you want truly "private" member data. \ (or have data you need to scrub)
# Co-opting / Appropriation
## prototype !== class
## prototype === polyfill