DEV Community

I think I finally “get” JS objects

Taylor Hunt on May 30, 2023

While learning JavaScript, at some point I looked up what “object-oriented” meant. That was a mistake. The first reason it was a mistake was beca...
Collapse
 
talmoscovitz profile image
talmoscovitz

Excellent article! I rarely find wikipedia pages useful - it's almost like their writers intentionally obfuscate the subject using irrelevant examples and overtly technical jargon fit for experts (not beginners). Who watches the watchers?

Collapse
 
guibleme profile image
Guilherme Barbosa Leme

Came to say the same. Awesome article!

Collapse
 
csdswarm profile image
Chris Strolia-Davis

In the early days of JavaScript, we used to specify that JS was object "based" not object "oriented". It has the concept of properties and methods and "looks" like it's object oriented. Indeed, you can even make work, to some extent, like an actual object oriented language.

The problem. It has ever been a prototypal language, and a dynamic one at that. The result is that people who try to shoehorn it into the OOP paradigm often finds that it works until it completely falls apart. And at the point it completely falls apart, you start to realize that the seeds of that were sown months before and are nearly impossible to remove by the time you realize the problem.

Whenever possible, I've come to do anything I can to avoid the this keyword. With the exception of using libraries and frameworks that force me to, I've found that I never need to use classes in JS, and since doing this, my life has never been easier (except when I end up working with other JS devs that are class evangelists).

Understanding closures in JS takes a little getting used to, but once you get it, I find that the resulting ways of handling object creation with factories and composition are much easier to write, understand and maintain than trying to follow an OOP paradigm.

Collapse
 
squidbe profile image
squidbe

As someone who's been writing JavaScript since 1999, I've found it interesting to see the language change over the years. As for objects, the key is to understand and embrace prototypal inheritance. Adding classical syntax in es6 muddied the waters and made some people think that JS inheritance had actually become classical, but as Doug Crockford used to say, it was just syntactic sugar -- still prototypes under the hood.

Spend some time understanding prototypes and prototypal inheritance -- it's not very complicated, and it makes sense if you don't try to force the classical model onto it.

Collapse
 
steveknoblock profile image
Steve Knoblock

JavaScript objects have many qualities of objects from OOP such as they consist of groups of properties which consist of property name-property value pairs. They do have an object feel to them that is palpable because of this. Values are accessed by property name. The name is “called” on the name similar to object methods. The JavaScript objects feels coherent and contained although not encapsulated. By having essentially a namespace in front of the property name, a kind of mild encapsulation is achieved.

All this makes objects very flexible. Too flexible for OOP mavens, but others have other opinions. Objects just exist by their declaration in object notation or through computation.

The associative array data structure, popularly referred to nowadays as a dictionary, is equivalent to the structure of an object. Perl is a language that offers associative arrays, called hashes because of how values are stored and accessed randomly. In Perl you are free to build as much OOP as you care to.

Collapse
 
peerreynders profile image
peerreynders • Edited

“Tables are the main (in fact, the only) data structuring mechanism in Lua, and a powerful one.”

Sound familiar? Unfortunately JavaScript objects are typically introduced in learning materials as a poor excuse for class instances rather than a “data structuring mechanism.”

this gets similar treatment. With traditional functions it's just something like an implicit calling environment parameter. If a function is called as a method the environment happens to be the object it was called on.

But this can be something else entirely, e.g.

import server$, { type ServerFunctionEvent } from 'solid-start/server';

async function connectServerSource(this: ServerFunctionEvent) {
  //...
}

const source = server$(connectServerSource);

//...
Enter fullscreen mode Exit fullscreen mode

where

interface ServerFunctionEvent {
  request: Request;
  env: Env;
  clientAddress: string;
  locals: Record<string, unknown>;
  fetch(url: string, init: RequestInit): Promise<Response>;
}
Enter fullscreen mode Exit fullscreen mode

i.e. the function to be executed server side is (independently) user defined but when executed this holds information and capabilities that only are relevant (yet indispensable) for very occasional, advanced use cases.

Collapse
 
drazisil profile image
Molly Crendraven

For anyone confused by this syntax, it's helpful to note that Interface is Typescript, not quite JavaScript. 😊

Collapse
 
minatop10 profile image
Mina

…doesn’t seem that much more useful than using hex codes directly in JS like 0xff28b1ff. But by making an actual color Object you can new up, we can add useful features, such as:

From a technical standpoint, JavaScript's object-oriented code may not align with the expectations derived from other languages. What struck me as a relatively beginner-level javascript dev is how you tinkered with CSS. Now I can't unsee how CSS really looks like an object.

Great read Taylor.

Collapse
 
efpage profile image
Eckehard

One of the core principles of OO is NOT TO USE global scopes. It is hard to imagine CSS that is only defined inside an object. Maybe this can partly establish something like a "local" CSS.

Collapse
 
codingjlu profile image
codingjlu

The thing about JavaScript is that objects are not what other languages call objects. In most languages an "object" comes from OOP. In JS an object does (did) not have anything to do with OOP. It's mostly equivalent to a Python dictionary, but slightly more powerful. OOP was not added to JS until ES6. In OOP an object is an instance of a class. JavaScript kind of seriously intertwined all that and basically made an instance a normal JS object. Gets kind of confusing, but makes sense when you think of it. 🥔

Collapse
 
urielsouza29 profile image
Uriel dos Santos Souza

Prototype is OOP.
Prototype-based programming is a style of object-oriented programming

Collapse
 
efpage profile image
Eckehard

I totally agree, Javascript is confusing in that specific point. And while JS classes look very similar to classes in other languages, the class model lacks some important features like strong encapsulation and a good control of visibility. Slowly it catches up introducing "private" variables in ES2023. But in fact, classes are not that useful as they are in C++ or Object-Pascal. But using them only for grouping of variables is still a bit underrated. Using Setters and getters can in any way be helpful to create reliable and good protected structures in JS.

Collapse
 
randy5235 profile image
Randy Wressell

My favorite part of all this is when all the Java and C# devs start clamoring about typescript and then write Java like code is TS and then complain that is still isnt quite right

Collapse
 
ukiyo profile image
Sunandini

As a beginner,I got little confused 🤔 in

  • Namespacing
  • Typed-ish data
  • Actual full-power Objects 😞 If I want to understand more about above topics , from where should I start? 🫠
Collapse
 
peerreynders profile image
peerreynders

Written this way…

const names = [
  'sunday',
  'monday',
  'tuesday',
  'wednesday',
  'thursday',
  'friday',
  'saturday',
];
const name = (index) => names[index];
const number = (name) => names.indexOf(name.toLowerCase());

const index = number('wednesday');
console.log(index);
// → 3
console.log(name(index));
// → wednesday
Enter fullscreen mode Exit fullscreen mode

…the three variable names names, name and number are “occupied” at the top level (i.e. they “pollute” it as nothing else can now use these variable names).

Compare this to…

const weekDay = (() => {
  const names = [
    'sunday',
    'monday',
    'tuesday',
    'wednesday',
    'thursday',
    'friday',
    'saturday',
  ];

  return {
    name(index) {
      return names[index];
    },
    number(name) {
      return names.indexOf(name.toLowerCase());
    },
  };
})();

const index = weekDay.number('wednesday');
console.log(index);
// → 3
console.log(weekDay.name(index));
// → wednesday
Enter fullscreen mode Exit fullscreen mode

Only weekDay is used as a top level variable name. The name() and number() functions are “namespaced” behind weekDay and names isn't accessible at all. And names, name and number can still be used as variable names on the top level for something more important.

“Typed-ish data” is just a standardized grouping of data that may (or may not) have some associated methods that use or act on the data contained inside the object.
See objects, methods.

“Actual full-power Objects” typically deals with the whole Class-Responsibility-Collaboration thing, i.e. class-orientation.

See The Secret Life of Objects.

In JavaScript Classes primarily exist to keep people happy who learned programming the class-oriented way first.

You only really need to use them when implementing Web Components as custom elements have to extends HTMLElement

Collapse
 
ukiyo profile image
Sunandini

Thank you 😃 @peerreynders , You explained very nicely, now I understood JS object bit more, Thank you soo much for this explanation 🤩

Collapse
 
efpage profile image
Eckehard

This reminded me to finish this post about inheritance, which is something I am missing in your post. Combined with a fine grained scope control this is a strong feature and a core quality of OOP.