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

@bblocks/compose

v0.1.2

Published

This library is a handy helper if you work with objects, inheritance and composition, like to code efficiently and need to support all modern browser and IE11 without transpiling.

Downloads

232

Readme

Discover super powers of composition and inheritance in javascript with compose library

This library is a handy helper if you work with objects, inheritance and composition, like to code efficiently and need to support all modern browser and IE11 without transpiling.

Quick start

Solving problem #1: Composition of objects keeping property descriptors

Solving problem #2: IE11 doesn't support Object.assign, Object.getOwnPropertyDescriptors

Solving problem #3: Bulky code to define properties, inherit and compose object using native javascript methods

Have some fun

Quick start

install

npm install @bblocks/compose --save-dev

include

<!-- include the library -->
<script src="https://cdn.jsdelivr.net/npm/@bblocks/[email protected]/compose.umd.js"></script>
// Optionally create shortcuts in lodash style 
var _ = Object.assign(_ || compose); // Now you can use helpers from the library_.mix  _.clone _.Block _.block

enjoy


// Composition
_.mix({prop1: 1}, {prop2: 2});

// Inheritance
_.clone({prop1: 1}, {prop2: 2}, {foo: function() {}});

// Handy object with built-in features to compose, clone and define properties
var myObj = new _.Block({prop1:1}); // Our building block
var myClone = myObj
	.mix({prop2:2}) 
	.define({
		prop3: {
			get: function() {return 3},
		}
	})
	.clone({prop4: 4});

// Check results
console.log(myClone.__proto__, myClone.prop1, myClone.prop2, myClone.prop3, myClone.prop4); // {...} 1 2 3 4

Problem: Composition of objects keeping property descriptors

Objects became more powerful in javascript since ES5. Now we can create super powerful objects thanks to property descriptors.

Let me show you. In the first example we create and object that can display numbers with suffixes like 1M, 1k, 1b etc...

// Display big numbers with suffixes
var bigNumber = {
	suffixes: ["", "k", "m", "b","t"],
	toString: function (value) {
		var newValue = value;
		if (value >= 1000) {
			var suffixes = this.suffixes;
			var suffixNum = Math.floor( (""+value).length/3 );
			var shortValue = '';
			for (var precision = 2; precision >= 1; precision--) {
				shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision));
				var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,'');
				if (dotLessShortValue.length <= 2) { break; }
			}
			if (shortValue % 1 != 0)  shortNum = shortValue.toFixed(1);
			newValue = shortValue+suffixes[suffixNum];
		}
		return newValue;
	}
};
console.log('100000 = ' + bigNumber.toString(100000)); // 1000000 = 1m 
// We can automatically generate a short string when value changes thanks to getters and setters 
Object.defineProperty(bigNumber, 'value', {
	get: function() {
		return this._value || 0;
	},
	set: function(newValue) {
		if (newValue != this._value) {
			this.stringValue = this.toString(newValue);
		}
		this._value = newValue;
	}
});
// Create a new instance
var myNumber = Object.create(bigNumber);
myNumber.value = 1000;
console.log(myNumber.value + ' = ' + myNumber.stringValue); // 1000 = 1k

I discovered a problem that we loose all property descriptors when we try to compose two objects.

// Define a new feature to increment a number
var increment = {
	increment: function() {
		this.value = (this.value || 0) + 1;
	}
}

// Compose increment and big number features  
var incNumber = Object.create(increment);
Object.assign(incNumber, bigNumber);

incNumber.increment(); // value = 1;

console.log(incNumber.value); // 1
console.log(incNumber.stringValue); // undefined :(

So we lost all the magic after composition. But you can use mix or clone methods from the library to solve this problem.

// Re-define our mixed object
var myIncNumber = _.clone(increment);
_.mix(myIncNumber, bigNumber);
// or
var myIncNumber2 = _.clone(increment, bigNumber);


myIncNumber.increment();
myIncNumber2.value = 1000;
console.log(myIncNumber.stringValue, myIncNumber2.stringValue); // 1, 1k

IE11 doesn't support Object.assign, Object.getOwnPropertyDescriptors

We can use native javascript function Object.assign for composition.

var sourceObj = {prop1:1};
Object.assign(sourceObj, {prop2: 2}); // Fails in IE11
console.log(sourceObj.prop1 + sourceObj.prop2); // 3

But in order to keep descriptors we need to use something like this.

var sourceObj = {prop1:1};
var extraObj = Object.defineProperty({}, 'prop2', {get: function() {return 2;}});
Object.defineProperties(sourceObj, Object.getOwnPropertyDescriptors(extraObj)); // Fails in IE11. Object doesn't support property or method 'getOwnPropertyDescriptors'
console.log(sourceObj.prop1 + sourceObj.prop2); // 3

Besides helpful mix and clone methods the library goes with two polyfills. Including the library automatically fixes the problem in IE11.

Problem: Bulky code to define properties, inherit and compose object using native javascript methods

The example above looks bulky in native JS code.

var sourceObj = {prop1:1};
var extraObj = Object.defineProperty({}, 'prop2', {get: function() {return 2;}});
Object.defineProperties(sourceObj, Object.getOwnPropertyDescriptors(extraObj));
console.log(sourceObj.prop1 + sourceObj.prop2); // 3

Library has a bonus for you. A handy Block you can start with.

var extraObj = (new _.Block()).define({prop2: {get: function() {return 2;}}});
var sourceObj = (new _.Block({prop1:1})).mix(extraObj);
console.log(sourceObj.prop1 + sourceObj.prop2); // 3

Let me explain step by step.

// create new objects 
var obj = new _.Block({prop1:1}); 

// composing with other objects
obj.mix({prop2: 2}); 

// configuring properties with descriptors
obj.define({prop3: {get: function() {return 3;}}});

// inherit
var myClone = obj.clone({prop4: 4});

// Checking results
console.log(myClone.prop1 + myClone.prop2 + myClone.prop3 + myClone.prop4); // 1 + 2 + 3 + 4 = 10

// You can use multiple arguments and chaining
var myClone = (new _.Block({prop1: 1}))
		.mix({prop2: 2})
		.define({prop3: {get: function() {return 3;}}})
		.clone({prop4: 4});

// Checking results
console.log(myClone.prop1 + myClone.prop2 + myClone.prop3 + myClone.prop4); // 1 + 2 + 3 + 4 = 10