npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

poopy.js

v1.0.0

Published

`poopy.js` ========== P.O.O.P., or “Prototype–Object Oriented Programming,” is a style of programming wherein one focuses on the development of prototype objects, which will then beget copies of themselves on which the data is intended to be changed.

Downloads

3

Readme

poopy.js

P.O.O.P., or “Prototype–Object Oriented Programming,” is a style of programming wherein one focuses on the development of prototype objects, which will then beget copies of themselves on which the data is intended to be changed.

Unlike classist systems, ‘POOP–y’ systems differentiate not–at–all between descendant and ancestor; any object can beget copies of itself. This means that once one has added functionality as they see fit to an object, they can immediately make use of that added functionality on any further datasets (objects).

poopy.js provides only a single useful method to facilitate POOPy programming. Instead of providing a great surfeit of added functionality to JavaScript itself, poopy.js operates as a contract: libraries depending on poopy.js are written in a POOPy style, and are intended to be used with poopy.js’s extensions.

Style & Use

Let’s look at a simple example, describing how one would use a standard JavaScript library, and then let’s look at how one would use a POOPy library.

We’ll say our example library is called Widget, and that it provides three kinds of functionality: a general function which prepares a ‘widget–y’ environment, the ability to create ‘widgets’ (a type of JavaScript object, of course), and the ability to create ‘snorklebobs’ (again, JavaScript objects).

Proto methods

Let’s first look at utilizing the general function (in POOPy terms, a ‘proto method’—one intended to be executed on the prototype, instead of on descendants), first in standard JavaScript:

var Widget = new(Function);
Widget.prepare = function () {
  // …
};

Widget.prepare();

Pretty standard, no? Let’s do the same thing, but with poopy.js:

var widget = {};
widget['prepare'] = function () {
  // …
};

widget.prepare();

Not really that different. Notice that we don’t use JavaScript’s new keyword; there are quite a few niggling details to deal with and, quite frankly, it’s extremely broken. Instead, we deal exclusively with objects themselves, asking objects to beget to new objects their data and functionality. Also notice that we are not inheriting our new objects from Function, instead, we simply create an empty basic object (created, in this case, with an object literal; new(Object) is just as valid, but I prefer to avoid any use of the new keyword entirely).

Begat methods

Let’s move on to creating a descendant, and utilizing one of our object’s methods intended for use on descendants (a ‘begat method’ in POOPy terms).

In standard JavaScript, you can’t easily create descendants of other arbitrary objects (even though it is, nominally, a prototypal language); instead, you only create descendants of special objects (in reality, functions) created specifically for this particular purpose (notationally, we traditionally reference these special–purpose objects by names starting with a capital letter, such as Object).

Let’s look at this in practice:

var Widget = new(Function);
Widget.prototype.toString = function () {
  // …
};

aWidget = new(Widget);
aWidget.toString();

Pretty ugly, right? We have to differentiate between the Widget object, and the methods intended for descendants (well, really, the children; there’s no easy way to create descendants of the descendants you create with new Widget(), so you’re effectively limited to one level of depth).

This becomes much more sensible with poopy.js:

var widget = {};
widget['toString'] = function () {
  // …
};

aWidget = widget.beget();
aWidget.toString();

Namespaced objects

It’s worth noting that namespaced objects will also be inherited.

Normal JS:

var Widget = new(Function);
Widget.Snorklebob = new(Function);
Widget.Snorklebob.prototype.toString = function () {
  // …
};

aSnorklebob = new(Widget.Snorklebob);
aSnorklebob.toString();

POOPy JS:

var widget = {};
widget['snorklebob'] = {};
widget.snorklebob['toString'] = function () {
  // …
};
  
aSnorklebob = widget.snorklebob.beget();
aSnorklebob.toString();

Constructor functions

When an object begets another object, it invokes the ancestor object’s constructor function with the new keyword. Normally, when none is defined, this is inherited from Object.prototype.constructor, which itself is just the Object function itself (a simple noop function); however, you are free to override this function to preform any preparation you desire on your newly created descendant.

Let’s take a simple example, that initializes a Widget with either a given value for foo, or, alternatively, a randomly generated string.

var Widget = function (blueprint) {
  this['foo'] = (typeof blueprint !== 'undefined' && blueprint.hasOwnKey('foo')) ?
    blueprint['foo'] : (Math.random() * 1e32).toString(36);
};

aWidget = new(Widget)({});
aWidget['foo']; //=> '1n0w4oy0797owwggosow'

Now in POOPy JS:

var widget = {};
widget['constructor'] = function (blueprint) {
  this['foo'] = (typeof blueprint !== 'undefined' && blueprint.hasOwnKey('foo')) ?
    blueprint['foo'] : (Math.random() * 1e32).toString(36);
};

aWidget = widget.beget({});
aWidget['foo']; //=> '225wep9t9yrogg0s00o8g'

This method of executing the constructor mitigates many of the problems inherent to the new keyword; it’s also simply a more purist form of traditional prototypal style than the alternatives.

Attributions

The primary code for this system is the Object.beget() method; this method’s original form was published in Douglas Crockford’s “JavaScript: The Good Parts”… however, the code has largely divorced from its original form (as therein published). Still, some credit for the concept is due him.

I would also like to thank Mr. Crockford, in general, for having written that book; it’s an absolutely wonderful learning tool, and it’s the first computer– related book that has actually taught me something… something I couldn’t just learn from a bit of Googling. That makes it the first, and last, useful treatise on programming to have ever passed my purview.