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

clank

v2.0.3

Published

lightweight inheritance and compositional object model; mostly just helpers

Downloads

39

Readme

Clank

A simple prototypal inheritance abstraction with an emphasis on composition. Clank adds some OO inheritance around cobble and works best with it. If you used Backbone or Ember this API should feel familiar, there is no magic here, just a few wrappers around the normal prototypal inheritance. Ultimately the goal would be to depreciate Clank when es6 classes are supported and just use them with cobble.

It is highly recommended that you take a look at the tests (./test/class.js) for a far more extensive demostration of the functionality of Clank.

Browser Support

Works fine in IE8 but does expect certain es5 functions, include es5 shim and sham in IE8 and everything will work fine, with a single caveat: object constructors are assigned a non-enumerable property __META__, which in IE8 is enumerable, so keep that in mind, when using Object.assign and other "extend" functions.

API

require the module;

var ClankObject = require('clank').Object

The Clank module is an object that exports a single property .Object.

Clank.Object

.extend(...spec)

Every Constructor returned from .extend() also has an extend method.

var Human = Clank.Object.extend({ species: 'Homo Sapien' })
var Jimmy = Human.extend({ name: Jimmy })

new Jimmy

You can also pass in multiple spec objects and make use of Clanks, underlying use of cobble.

var Person = Clank.Object.extend({ species: 'homo sapian', limbs: 4 })
  , docOctMixin = { limbs: 8 }
  , DocOct = Person.extend(docOct, { gender: 'male' });

var doc = new DocOct()
doc.limbs // => 8

This effectively means that you can specify mixin objects before your prototype spec.

You can also use cobble's descriptors to handle overrides and super calls. See the cobble documentation for more information on descriptors

var EnglishSpeaker  = Clank.Object.extend({ greet: function(){ return "hello" } })

var spanishGreeting = { greet: function(){ return "hola" } }
var germanGreeting  = { greet: function(){ return "guten morgen" } }

var GermanSpanishAmerican = EnglishSpeaker.extend(spanishGreeting, germanGreeting, { 
      greet: cobble.reduce(function (target, next) {
        return function(){
          return target.call(this) + " and " + next.call(this)
        }
      }) 
    });

var person = new GermanSpanishAmerican()

person.greet() // => "hello and hola and guten morgen"


// Super calls with Constructors
// ---------

var Machine = Clank.Object.extend({
       
       constructor: function(){
         Clank.Object.call(this) //call the super constructor in the traditional way
         
         this.greeting = (this.greeting || '') + 'whizz'
       }
     })
 
var Toaster = Machine.extend({ 

      // call the super Toaster constructor after the Toaster constructor using a Descriptor
      constructor: cobble.before(function(){
        this.greeting = 'whorl'
      })
    })

.reopen(...spec)

.reopen is like .extend but instead of creating a new Class it alters the current class prototype. Changes made to the prototype will cascade throguh the object heirarchy.

.reopen has the same signature as .extend.

var Person = Clank.Object.extend({ species: 'homo sapien'})
  , Man    = Person.extend({ gender: 'male' });

var man = new Man()

man.gender // => 'male'
man.limbs  // => undefined

Man.reopen({
  limbs: 4,
  gender: 'irrelevant'
})

man.gender // => 'irrelevant'
man.limbs  // => 4

.create(...properties)

Returns an instance of the object with instance properties set to the passed in object, or array of objects. .create also has the same signature as .extend() so you can use descriptors as well to compose properties.

var Person = Clank.Object.extend({ greeting: 'guten tag' }); 

var me  = Person.create({ greeting: 'hello'})
  , friend = Person.create()

me.hasOwnProperty('greeting')     // => true
me.greeting                       // => 'hello'

friend.hasOwnProperty('greeting') // => false
friend.greeting                   // => 'guten tag'

Default Object Composition

In certain cases you may want to create an object Class with a default composition behaviour when extending or creating instances. Clank provides the Constructor.setCompositionStrategy(spec) method for doing just this. The provided spec should be an object of Descriptors that will be mixed into the instance or extension after all user provided compositions.

var Person = Clank.Object.extend({ traits: [ 'biped', 'hair'] });

// in the future traits will be concated together
Person.setCompositionStrategy({
  traits: cobble.concat()
})

var Hero  = Person.extend({ traits: [ 'brave' ] }) //no need to manually resolve this conflict

var  jimmy = new Hero;

jimmy.traits // => [ 'biped', 'hair', 'brave' ]

This can be very helpful for creating some default behaviour in an often used object, but beware, a user can still provide their own compositions, that run before the default strategy. If the user is unaware of the default strategy this can introduce subtle bugs when they try and duplicate a behaviour.

Super Calls

By default the descriptors, such as before() and after(), include super methods and properties, so they are composed together along with any mixins.

var Person = Clank.Object.extend({ 
      greet: function(name){
        return "hello"  + " " + name
      }
    }) 

var Pirate = Person.extend({ 
      greet: cobble.compose(function(greeting){
        return  "ARRRRRRG and " + greeting 
      })
    })

var blackBeard = new Pirate()

blackBeard.greet('Steven') // => "ARRRRRRG and hello Steven"

Clank does have a "proper" super implementation but you probably don't need it. The majority of super use-cases, can be solved by simple doing Parent.prototype[method].call(this, [args] or by using a Descriptor. Overuse of the super keyword can lead to bad patterns (like calling _super in a mixin object), and should be saved for situations when you cannot use a static reference, or you know the super method may change.

For a bunch of reasons, using _super is going to be less performant than a static reference (either method). Note: super also makes use of Function.caller, a depreciated js feature, internally.

In a few cases where you need to dynamically reference the super class, super han be accessed by this._super([method]) => returns the method inside a class method, however, there are a bunch of pitfalls and caveats related to its use, which is why it is underscored. Consult the tests for insight into the limitations of this method.