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

34rth-javascript-core-oo

v1.4.18

Published

An node/browser library to support full inheritance, mixins, private, public and static variables, event driven programming (publishing/subscribing to instance events) and a global caching mechanism.

Downloads

79

Readme

Build Status npm npm

TABLE OF CONTENTS

GENERAL

JavaScript (node.js/browser) library for inheritance and mixins in JavaScript with strong coupling of contexts. Includes private/public/static members/functions as well as mixin architecture (borrowing functionality from mixins);

The package/framework is 100% stand-alone and is not dependant on any other npm packages. The packages listed in node_modules are exclusively for the performance comparison modules required to compare the baseline performances.

INSTALLATION

in Node.js

npm install 34rth-javascript-core-oo

in Browser

Download the /bin/oo.js file from github

<script type="text/javascript" src="oo.js"></script>

EXAMPLES

Classes (private/public variables/functions)

The example below shows the private, public functions/members, static functions and variables as well as the constructor. See example file.

var earth = require('34rth-javascript-core-oo');

var my_class = earth.core.object.extend(function(_super){
  this.__id__ = 'my_class'; //this is optional for debugging purpose; definition does not have to be included
  
  this.statics = {};//define the statics object:
  this.statics.my_static_function = function(){
    console.log('Hooray, I\'m static');
  };

  this.statics.my_other_static_function = function(){
    console.log('So what, so am I...');
  };

  this.statics.STATIC_VALUE = 'I am like a rock...';

  this.member_variable = 'I am a variable and can be accessed from any instance';

  var private_variable = 'I am shy';

  //I am the constructor, all your base are belong to us
  this.__init = function(a, b, c){
    console.log('Constructing is as easy as ' + a + ' ' + b + ' ' + c);
  };

  this.public_function = function(){
    console.log('total extrovert');
  };

  var private_function = function(){
    console.log('not really introvert, but do not really fancy being seen everywhere, anytime...');
  };
});

//testing the statics
my_class.my_static_function();
my_class.my_other_static_function();
console.log(my_class.STATIC_VALUE);

var my_instance = new my_class(1,2,3);
my_instance.public_function();
try{
  my_instance.private_function();
}catch(e){
  console.log('really, really, really don\'t want to be called');
}
console.log(my_instance.member_variable);
console.log(my_instance.private_variable);//undefined... they said they're shy :) 

Simple class inheritance and _super

Code example for simple inheritance calling _super constructor and methods. See example file.

var earth = require('34rth-javascript-core-oo');

//definition of bicycle class - extending from the core class
var bicycle = earth.core.object.extend(function(_super){
  this.__id__ = 'bicycle';//this is optional for debugging purposes and can be any random string

  // the bicycle class has three public member variables
  this.cadence = null;
  this.gear = null;
  this.speed = null;

  //constructor function
  this.__init = function(start_cadence, start_speed, start_gear){
    this.gear = start_gear;
    this.speed = start_speed;
    this.cadence = start_cadence;
  };

  this.set_cadence = function(value){
    this.cadence = value;
  };

  this.set_gear = function(value){
    this.gear = value;
  };

  this.apply_brake = function(decrement){
    this.speed -= decrement;
  };
 
  this.speed_up = function(increment){
    this.speed += increment;
  };

  this.get_speed = function(){
    return this.speed; 
  };
});

//definition of mountain_bike class, inheriting from the bicycle class
var mountain_bike = bicycle.extend(function(_super){
  this.__id__ = 'bicycle.mountain_bike';//this is optional for debugging purposes and can be any random string

  //the mountain_bike class adds one more public member variable
  this.seat_height = null;

  //constructor function
  this.__init = function(start_height, start_cadence, start_speed, start_gear){
    _super.__init.call(this, start_cadence, start_speed, start_gear);//call super prototype
    this.seat_height = start_height;
  };

  this.set_height = function(value){
    this.seat_height = value;
  };

	//we're shadowing the function speed_up of bicycle
	this.speed_up = function(increment){
		//on a mountainbike we're speeding up much faster
		this.speed += increment*1.2;
	};

  //we're shadowing the function get_speed of bicycle
  this.get_speed = function(){
    //but we're calling the function of the parent 
    return _super.get_speed.call(this);
  };
});

var bicycle_instance = new bicycle(1, 10, 1);
var mountain_bike_instance = new mountain_bike(90, 1, 10, 1);

console.log(bicycle_instance.speed);//prints 10 as speed of has not been modified
bicycle_instance.speed_up(15);//speeding up by 15 (e.g. m/h)
console.log(bicycle_instance.speed);//prints 25 as speed of has not been modified
console.log(typeof bicycle_instance);//returns object
console.log(bicycle_instance instanceof earth.core.object);//prints true
console.log(bicycle_instance instanceof bicycle);//prints true
console.log(bicycle_instance instanceof mountain_bike);//prints false
try{
	bicycle_instance.set_height(5);
}catch(e){
  console.log('Bicycle does not have a set_height function');
}


console.log(mountain_bike_instance.speed);//prints 10 as speed of has not been modified
mountain_bike_instance.speed_up(5);//speeding up by 5 (e.g. m/h)
console.log(mountain_bike_instance.speed);//prints 16 (10+5*1.2);
console.log(mountain_bike_instance.get_speed() == mountain_bike_instance.speed);//returns true as shadowed function get_speed calls parent function get_speed, returning the current speed
console.log(typeof bicycle_instance);//returns object
console.log(mountain_bike_instance instanceof earth.core.object);//prints true
console.log(mountain_bike_instance instanceof bicycle);//prints true
console.log(mountain_bike_instance instanceof mountain_bike);//prints true 

Static functions

Defining and calling static functions on classes. See example file.

var earth = require('34rth-javascript-core-oo');

var my_static_class = earth.core.object.extend(function(_super){
  this.statics = [];

  this.statics.say_hello = function(name){
    console.log('Hello ' + name);
  };
});

my_static_class.say_hello('Peter');//prints "Hello Peter"

Static functions and inheritance

Inheriting and calling inherited static functions. See example file.

var earth = require('34rth-javascript-core-oo');

var my_parent_static_class = earth.core.object.extend(function(_super){
  this.statics = [];

  this.statics.say_hello = function(name){
    console.log('Hello ' + name);
  };
});

var my_child_static_class = my_parent_static_class.extend(function(_super){
  this.statics = [];

  this.statics.say_bye = function(name){
    console.log('Bye ' + name);
  };
});

my_child_static_class.say_hello('Marry');//prints "Hello Marry"
my_child_static_class.say_bye('Peter');//prints "Bye Peter"
my_parent_static_class.say_hello('Peter');//print "Hello Peter"
try{
  my_parent_static_class.say_bye('Marry');//is not defined and throws an Exception
}catch(e){
  console.log('I am not defined');
}

Init Hooks

Init hooks allow to trigger any number of callback functions whenever a new instance of a class is created. Init hooks traverse the whole prototype chain (ie parent's init hooks will also get triggered). See example file.

var my_class = earth.core.object.extend(function(_super){
  this.__init = function(number){
    console.log('Yaaay, the constructor was just called');
    this.number = number;
  };
});

my_class.add_init_hook(function(_super){
  console.log('Class has been initialised with number ' + this.number);
});

new my_class(10);
//'Yaaay, the constructor was just called
//Class has been initialised with number 10

Init Hooks and _super

Init hooks also allow access to _super (always in context) so shadowed functions can be called. See example file.

var earth = require('34rth-javascript-core-oo');

var my_class = earth.core.object.extend(function(_super){
  this.__init = function(number){
    console.log('Yaaay, the constructor just was called');
    this.number = number;
  };

  this.my_special_function = function(){
    console.log('I am ' + this.number + ' times more special than anyone else!');
  };
});

var my_child_class = my_class.extend(function(_super){
  this.__init = function(number){
    _super.__init.call(this, number);
  };
  
  this.my_special_function = function(){
    console.log('Me toooooooo!');
  };
});

my_child_class.add_init_hook(function(_super){
  console.log('Class has been initialised with number ' + this.number);
  _super.my_special_function.call(this);
  this.my_special_function();
});

new my_child_class(10);
//Yaaay, the constructor just was called
//Class has been initialised with number 10
//I am 10 times more special than anyone else!
//Me toooooooo!

Mixins

Mixins can be used to implement functionality that can be shared between classes. As a class can only inherit from one other class (JAVA-style) mixins allow a way to reduce duplication of code (think aspect oriented programming in JAVA). See example file.

var earth = require('34rth-javascript-core-oo');

var speaker = earth.core.mixin.extend(function(_super){
  this.say_something = function(){
    console.log('something');
  };
});

//mixins can also inherit from other mixins
var hello = earth.core.mixin.extend(function(_super){
  this.say_hello = function(name){
    console.log('Hello ' + name);
  };
});

var bye = earth.core.mixin.extend(function(_super){
  this.say_goodbye = function(name){
    console.log('Bye ' + name);
  };
});

var app = earth.core.object.extend(function(_super){
  this.includes = [speaker, hello, bye];//array of mixins to include
});


var test = new app();

test.say_something();//Prints "Something"
test.say_hello('Marry');//prints "Hello Marry"
test.say_goodbye('Marry');//prints "Bye Marry"

Mixins and Inheritance

Mixins can also inherit functions (including full inheritance logic). See example file.

var earth = require('34rth-javascript-core-oo');

var speaker = earth.core.mixin.extend(function(_super){
  this.say_something = function(){
    console.log('something');
  };
});

//mixins can also inherit from other mixins
var speaker_with_good_memory = speaker.extend(function(_super){
  this.names = [];

  this.say_hello = function(name){
    this.names.push(name);
    console.log('Hello ' + this.names.join(', '));
  };
});

var app = earth.core.object.extend(function(_super){
  this.includes = [speaker, speaker_with_good_memory];//array of mixins to include
});


var test = new app();

test.say_something();//Prints "Something"
test.say_hello('Peter');//prints "Hello Peter"
test.say_hello('Marry');//prints "Hello Peter, Marry"
test.say_hello('Charly');//prints "Hello Peter, Marry, Charly"

Mixin and chaining

Trivially, all calls can be chained if desired, by returning this. See example file.

var earth = require('34rth-javascript-core-oo');

var speaker = earth.core.mixin.extend(function(_super){
  this.say_something = function(){
    console.log('something');
    return this;//returns a reference to the object mixing
  };
});

//mixins can also inherit from other mixins
var speaker_with_good_memory = speaker.extend(function(_super){
  this.names = [];

  this.say_hello = function(name){
    this.names.push(name);
    console.log('Hello ' + this.names.join(', '));
    return this;//returns a reference to the object mixing
  };
});

var app = earth.core.object.extend(function(_super){
  this.includes = [speaker, speaker_with_good_memory];//array of mixins to include
});


var test = new app();

test.say_something().say_hello('Peter').say_hello('Marry').say_hello('Charly');

Syntactic sugar (super calls in every class)

There is an in-built option to enable syntactic super sugar to have direct reference to super methods throughout the private/public class functions. Please note that the super sugar comes at a performance penalty of roughtly 40% compared to the results in the PERFORMANCE COMPARISON. The example below is the same as in Simple class inheritance and _super just with syntactic super sugar turned on.

Enabling the super sugar is done by passing the option {super:true} to the class definition as per the example file below.

var earth = require('34rth-javascript-core-oo');

//definition of bicycle class - extending from the core class
var bicycle = earth.core.object.extend(function(_super){
  this.__id__ = 'bicycle';//this is optional for debugging purposes and can be any random string

  // the bicycle class has three public member variables
  this.cadence = null;
  this.gear = null;
  this.speed = null;

  //constructor function
  this.__init = function(start_cadence, start_speed, start_gear){
    this.gear = start_gear;
    this.speed = start_speed;
    this.cadence = start_cadence;
  };

  this.set_cadence = function(value){
    this.cadence = value;
  };

  this.set_gear = function(value){
    this.gear = value;
  };

  this.apply_brake = function(decrement){
    this.speed -= decrement;
  };
 
  this.speed_up = function(increment){
    this.speed += increment;
  };

  this.get_speed = function(){
    return this.speed; 
  };
}, {super:true});

//definition of mountain_bike class, inheriting from the bicycle class
var mountain_bike = bicycle.extend(function(_super){
  this.__id__ = 'bicycle.mountain_bike';//this is optional for debugging purposes and can be any random string

  //the mountain_bike class adds one more public member variable
  this.seat_height = null;

  //constructor function
  this.__init = function(start_height, start_cadence, start_speed, start_gear){
    this.super(start_cadence, start_speed, start_gear);//call super prototype; EQUIVALENT TO: _super.__init.call(this, start_cadence, start_speed, start_gear);//call super prototype
    this.seat_height = start_height;
  };

  this.set_height = function(value){
    this.seat_height = value;
  };

	//we're shadowing the function speed_up of bicycle
	this.speed_up = function(increment){
		//on a mountainbike we're speeding up much faster
		this.speed += increment*1.2;
	};

  //we're shadowing the function get_speed of bicycle
  this.get_speed = function(){
    //but we're calling the function of the parent 
    return this.super();//EQUIVALENT TO: return _super.get_speed.call(this);
  };
}, {super:true});

var bicycle_instance = new bicycle(1, 10, 1);
var mountain_bike_instance = new mountain_bike(90, 1, 10, 1);

console.log(bicycle_instance.speed);//prints 10 as speed of has not been modified
bicycle_instance.speed_up(15);//speeding up by 15 (e.g. m/h)
console.log(bicycle_instance.speed);//prints 25 as speed of has not been modified
console.log(typeof bicycle_instance);//returns object
console.log(bicycle_instance instanceof earth.core.object);//prints true
console.log(bicycle_instance instanceof bicycle);//prints true
console.log(bicycle_instance instanceof mountain_bike);//prints false
try{
	bicycle_instance.set_height(5);
}catch(e){
  console.log('Bicycle does not have a set_height function');
}


console.log(mountain_bike_instance.speed);//prints 10 as speed of has not been modified
mountain_bike_instance.speed_up(5);//speeding up by 5 (e.g. m/h)
console.log(mountain_bike_instance.speed);//prints 16 (10+5*1.2);
console.log(mountain_bike_instance.get_speed() == mountain_bike_instance.speed);//returns true as shadowed function get_speed calls parent function get_speed, returning the current speed
console.log(typeof bicycle_instance);//returns object
console.log(mountain_bike_instance instanceof earth.core.object);//prints true
console.log(mountain_bike_instance instanceof bicycle);//prints true
console.log(mountain_bike_instance instanceof mountain_bike);//prints true 

PERFORMANCE COMPARISON

Performance comparison against the following libraries/scripts:

To run the performance tests, run

node performance/run_proprietary.js

There are two parameters available:

  • --benchmark/-b: the type of benchmark to run. Valid values: instantiation, public, static
  • --class/-c: the class that should be benchmarked.

Overall performance results

| # | Library | ops/ms | total time (in ms) | total sample size | | :-: | --- | --: | --: | --: | | 1 | 34rth | 13,355 | 4,151 | 40,000,000 | | 2 | augment | 12,663 | 4,372 | 40,000,000 | | 3 | native | 10,905 | 4,417 | 40,000,000 | | 4 | Lava.ClassManager monomorphic | 9,438 | 4,564 | 40,000,000 | | 5 | Typescript | 9,377 | 4,657 | 40,000,000 | | 6 | jsface | 10,140 | 4,965 | 40,000,000 | | 7 | Lava.ClassManager polymorphic | 8,958 | 5,348 | 40,000,000 | | 8 | inherits | 8,600 | 5,738 | 40,000,000 | | 9 | Fiber | 7,581 | 6,028 | 40,000,000 | | 10 | John Resig’s Class | 3,779 | 13,194 | 40,000,000 |

Specific performance per example

Instantiation (inheritance depth 1)

| # | Library | ops/ms | total time (in ms) | Sample Size | | :-: | --- | --: | --: | --: | | 1 | augment | 20,734 | 482.31 | 10,000,000 | | 2 | 34rth | 20,343 | 491.58 | 10,000,000 | | 3 | native | 16,965 | 589.45 | 10,000,000 | | 4 | jsface | 16,937 | 590.42 | 10,000,000 | | 5 | inherits | 13,381 | 747.34 | 10,000,000 | | 6 | Typescript | 13,336 | 749.87 | 10,000,000 | | 7 | Lava.ClassManager polymorphic | 12,748 | 784.42 | 10,000,000 | | 8 | Lava.ClassManager monomorphic | 12,093 | 826.93 | 10,000,000 | | 9 | Fiber | 11,161 | 895.98 | 10,000,000 | | 10 | John Resig's Class | 6,744 | 1,482.78 | 10,000,000 |

Instantiation (inheritance depth 2)

| # | Library | ops/ms | total time (in ms) | Sample Size | | :-: | --- | --: | --: | --: | | 1 | 34rth | 20,392 | 490.39 | 10,000,000 | | 2 | augment | 17,876 | 559.42 | 10,000,000 | | 3 | native | 13,636 | 733.37 | 10,000,000 | | 4 | Lava.ClassManager polymorphic | 12,426 | 804.77 | 10,000,000 | | 5 | jsface | 12,332 | 810.87 | 10,000,000 | | 6 | Lava.ClassManager monomorphic | 11,824 | 845.74 | 10,000,000 | | 7 | inherits | 11,194 | 893.31 | 10,000,000 | | 8 | Typescript | 10,630 | 940.72 | 10,000,000 | | 9 | Fiber | 9,210 | 1,085.78 | 10,000,000 | | 10 | John Resig's Class | 3,889 | 2,571.49 | 10,000,000 |

Public Method Invocation (inheritance depth 1)

| # | Library | ops/ms | total time (in ms) | Sample Size | | :-: | --- | --: | --: | --: | | 1 | Typescript | 7,215 | 1,385.91 | 10,000,000 | | 2 | native | 7,049 | 1,418.74 | 10,000,000 | | 3 | Lava.ClassManager monomorphic | 6,959 | 1,436.98 | 10,000,000 | | 4 | 34rth | 6,786 | 1,473.63 | 10,000,000 | | 5 | augment | 6,316 | 1,583.35 | 10,000,000 | | 6 | jsface | 6,088 | 1,642.56 | 10,000,000 | | 7 | Lava.ClassManager polymorphic | 5,530 | 1,808.43 | 10,000,000 | | 8 | Fiber | 5,381 | 1,858.52 | 10,000,000 | | 9 | inherits | 5,307 | 1,884.27 | 10,000,000 | | 10 | John Resig's Class | 2,581 | 3,875.01 | 10,000,000 |

Public Method Invocation (inheritance depth 2)

| # | Library | ops/ms | total time (in ms) | Sample Size | | :-: | --- | --: | --: | --: | | 1 | Lava.ClassManager monomorphic | 6,876 | 1,454.40 | 10,000,000 | | 2 | Typescript | 6,325 | 1,580.93 | 10,000,000 | | 3 | native | 5,968 | 1,675.62 | 10,000,000 | | 4 | 34rth | 5,899 | 1,695.13 | 10,000,000 | | 5 | augment | 5,725 | 1,746.59 | 10,000,000 | | 6 | jsface | 5,204 | 1,921.58 | 10,000,000 | | 7 | Lava.ClassManager polymorphic | 5,126 | 1,950.87 | 10,000,000 | | 8 | Fiber | 4,570 | 2,188.11 | 10,000,000 | | 9 | inherits | 4,519 | 2,213.08 | 10,000,000 | | 10 | John Resig's Class | 1,900 | 5,264.32 | 10,000,000 |

Static Method Invocation

| # | Library | ops/ms | total time (in ms) | Sample Size | | :-: | --- | --: | --: | --: | | 1 | 34rth | 14,559 | 686.88 | 10,000,000 | | 2 | Typescript | 13,608 | 734.84 | 10,000,000 | | 3 | jsface | 12,938 | 772.92 | 10,000,000 | | 4 | inherits | 12,279 | 814.38 | 10,000,000 | | 5 | native | n\a | n\a | n\a | | 6 | John Resig's Class | n\a | n\a | n\a | | 7 | Fiber | n\a | n\a | n\a | | 8 | Lava.ClassManager polymorphic | n\a | n\a | n\a | | 9 | Lava.ClassManager monomorphic | n\a | n\a | n\a | | 10| augment | n\a | n\a | n\a |

TESTS

For mocha test results see Travis CI.

node make.js && ./node_modules/mocha/bin/mocha