New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

heir

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

heir - npm Package Compare versions

Comparing version 1.0.1 to 2.0.0

sauce_connect.log

2

bower.json
{
"name": "heir",
"description": "Makes prototypical inheritance easy and robust",
"version": "1.0.1",
"version": "2.0.0",
"main": [

@@ -6,0 +6,0 @@ "./heir.js"

/**
* Heir v1.0.1 - http://git.io/F87mKg
* Heir v2.0.0 - http://git.io/F87mKg
* Oliver Caldwell

@@ -7,128 +7,99 @@ * MIT license

(function () {
(function (name, root, factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
}
else if (typeof exports === 'object') {
module.exports = factory();
}
else {
root[name] = factory();
}
}('heir', this, function () {
/*global define,module*/
'use strict';
/**
* Works out if a variable is a true object (created with {} etc) and not an array or anything else that usually shows up as an object.
*
* @param {Mixed} chk The variable to check to see if it is an object. It must be a pure object, not even a prototype.
* @return {Boolean} True if it is a true object, false if it is anything else.
*/
function isObject(chk) {
return (chk && Object.prototype.toString.call(chk) === '[object Object]') === true;
}
var heir = {
/**
* Causes your desired class to inherit from a source class. This uses
* prototypical inheritance so you can override methods without ruining
* the parent class.
*
* This will alter the actual destination class though, it does not
* create a new class.
*
* @param {Function} destination The target class for the inheritance.
* @param {Function} source Class to inherit from.
* @param {Boolean} addSuper Should we add the _super property to the prototype? Defaults to true.
*/
inherit: function inherit(destination, source, addSuper) {
var proto = destination.prototype = heir.createObject(source.prototype);
proto.constructor = destination;
if (addSuper || typeof addSuper === 'undefined') {
proto._super = source.prototype;
}
},
/**
* Recursively merges two objects. Object `a` will be overridden by the values in object `b`.
* Please run the values through a cloning function first, this function does not try to clone them for you.
* The base object will be edited directly, please be careful!
*
* @param {Object} a The base object to merge into.
* @param {Object} b The object to merge down into object `a`.
* @return {Object} This is object `a` but merged with `b`.
*/
function merge(a, b) {
// Loop over all values in b. If they are not found in a then set them
// If both values are objects then recursively merge them
for (var key in b) {
// Make sure the value is not in __proto__ or something like that
if (b.hasOwnProperty(key)) {
// If they are both objects then merge recursively
if (isObject(a[key]) && isObject(b[key])) {
merge(a[key], b[key]);
}
/**
* Creates a new object with the source object nestled within its
* prototype chain.
*
* @param {Object} source Method to insert into the new object's prototype.
* @return {Object} An empty object with the source object in it's prototype chain.
*/
createObject: Object.create || function createObject(source) {
var Host = function () {};
Host.prototype = source;
return new Host();
},
// Otherwise just replace the base value
else {
a[key] = b[key];
}
}
}
/**
* Mixes the specified object into your class. This can be used to add
* certain capabilities and helper methods to a class that is already
* inheriting from some other class. You can mix in as many object as
* you want, but only inherit from one.
*
* These values are mixed into the actual prototype object of your
* class, they are not added to the prototype chain like inherit.
*
* @param {Function} destination Class to mix the object into.
* @param {Object} source Object to mix into the class.
*/
mixin: function mixin(destination, source) {
return heir.merge(destination.prototype, source);
},
// Return the merged object
return a;
}
/**
* Merges one object into another, change the object in place.
*
* @param {Object} destination The destination for the merge.
* @param {Object} source The source of the properties to merge.
*/
merge: function merge(destination, source) {
var key;
/**
* Returns a recursive clone of the passed object.
* So when you edit the original the clone will not change.
* Used in prototypical inheritance.
* It will not clone arrays.
*
* @param {Object} orig The original object to clone.
* @return {Object} The cloned version of orig that can be edited without changing the original.
*/
function clone(orig) {
// Initialise variables
var cl = {};
var key;
// Loop over all values in the object
// If the value is an object then clone recursively
// Otherwise just copy the value
for (key in orig) {
if (orig.hasOwnProperty(key)) {
cl[key] = isObject(orig[key]) ? clone(orig[key]) : orig[key];
for (key in source) {
if (heir.hasOwn(source, key)) {
destination[key] = source[key];
}
}
}
},
// Return the clone
return cl;
}
/**
* Inherits other functions prototype objects into the current function.
*
* @param {Function|Function[]} parent A function which should have it's prototype cloned and placed into the current functions prototype. If you pass an array of functions they will all be inherited from.
* @param {Function} [forceFn] Optional function to use as the current function which is inheriting the other prototypes. It will default to `this`.
* @return {Function} The current function to allow chaining.
*/
function inherit(parent, forceFn) {
// Initialise variables
var fn = forceFn || this;
var i;
// If the parent variable is not a function then it must be an array
// So we have to loop over it and inherit each of them
// Remember to pass the current function instance!
if (typeof parent !== 'function') {
i = parent.length;
while (i--) {
inherit(parent[i], fn);
}
/**
* Shortcut for `Object.prototype.hasOwnProperty`.
*
* Uses `Object.prototype.hasOwnPropety` rather than
* `object.hasOwnProperty` as it could be overwritten.
*
* @param {Object} object The object to check
* @param {String} key The key to check for.
* @return {Boolean} Does object have key as an own propety?
*/
hasOwn: function hasOwn(object, key) {
return Object.prototype.hasOwnProperty.call(object, key);
}
else {
// It is not an array, it is a plain function
// Merge it's prototype into this one
merge(fn.prototype, clone(parent.prototype));
}
// Return the current function to allow chaining
return fn;
}
// Expose the inherit function by placing it in the Function prototype
Function.prototype.inherit = inherit;
// Create a nice little namespace to expose
var ns = {
isObject: isObject,
merge: merge,
clone: clone,
inherit: inherit
};
// And expose everything else either via AMD or a global object
if (typeof define === 'function' && define.amd) {
define(function () {
return ns;
});
}
else if (typeof module === 'object' && module.exports) {
module.exports = ns;
}
else {
this.heir = ns;
}
}.call(this));
return heir;
}));
{
"name": "heir",
"version": "1.0.1",
"version": "2.0.0",
"description": "Makes prototypical inheritance easy and robust",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -8,16 +8,29 @@ # Heir

```javascript
// Create the base class
var Base = function(){};
// Create the base class.
function Base() {}
// Add a method
Base.prototype.foo = function() {
retrun '!foo!';
// Add a method.
Base.prototype.foo = function () {
return 'Base#foo';
};
// Create a sub class which inherits from base
var Sub = function(){}.inherit(Base);
// Create a sub class which inherits from base.
function Sub() {}
heir.inherit(Sub, Base);
// Create an instance of Sub and call it's method
// Mix in some functionality enhancing objects.
heir.mixin(Sub, events);
heir.mixin(Sub, pooling);
// Change the original method.
Sub.prototype.foo = function () {
return [
'Sub#foo',
this._super.foo.call(this)
].join(', ');
};
// Create an instance of Sub and call it's method.
var s = new Sub();
s.foo(); // Returns "!foo!"
s.foo(); // Returns "Sub#foo, Base#foo"
```

@@ -27,2 +40,10 @@

## Changes from v1
The `inherit` method used to work by cloning and merging multiple prototypes into one. This meant things like `instanceof` didn't work and you could get into some weird scenarios [caused by multiple inheritance][mi].
The new `inherit` uses the built in prototypical inheritance to provide a much cleaner outcome, as shown in [this post about prototypical inheritance][pi]. The major change is that you can't inherit from multiple classes any more.
If you still need to have multiple things shared between classes to avoid duplication, you can now use the `mixin` method to merge objects into your inheritance hierarchies where required.
## Downloading

@@ -50,3 +71,3 @@

Heir will always be tested and working perfectly in all of them before a release. I will not release anything I think is riddled with bugs. However, if you do spot one, please [submit it as an issue](https://github.com/Wolfy87/Heir/issues) and I will get right on it.
Heir will always be tested and working perfectly in all of them before a release. I will not release anything I think is riddled with bugs. However, if you do spot one, please [submit it as an issue][issues] and I will get right on it.

@@ -64,2 +85,5 @@ ## License (MIT)

[npm]: https://npmjs.org/
[bower]: http://bower.io/
[bower]: http://bower.io/
[issues]: https://github.com/Wolfy87/Heir/issues
[mi]: http://stackoverflow.com/questions/225929/what-is-the-exact-problem-with-multiple-inheritance
[pi]: http://oli.me.uk/2013/06/01/prototypical-inheritance-done-right/

@@ -5,3 +5,2 @@ (function () {

// Set up the Jasmine environment
var jasmineEnv = jasmine.getEnv();

@@ -18,231 +17,150 @@ jasmineEnv.updateInterval = 1000;

// Configure the tests
describe('heir.isObject', function() {
it('returns true on objects', function() {
expect(heir.isObject({})).toBe(true);
var test = {};
expect(heir.isObject(test)).toBe(true);
});
describe('heir.createObject', function () {
it('returns a new empty object when passed one', function () {
var source = {};
var result = heir.createObject(source);
it('returns false on a regex', function() {
expect(heir.isObject(/reg[ex]/i)).toBe(false);
var test = /reg[ex]/i;
expect(heir.isObject(test)).toBe(false);
expect(result).toEqual({});
expect(result).not.toBe(source);
});
it('returns false on arrays', function() {
expect(heir.isObject([])).toBe(false);
var test = [];
expect(heir.isObject(test)).toBe(false);
});
it('inserts the source object into the prototype', function () {
var source = {
foo: true
};
var result = heir.createObject(source);
it('returns false on null', function() {
expect(heir.isObject(null)).toBe(false);
var test = null;
expect(heir.isObject(test)).toBe(false);
expect(result).toEqual(source);
expect(result).not.toBe(source);
expect(result.hasOwnProperty('foo')).toBe(false);
expect(result.foo).toBe(true);
});
it('returns false on numbers', function() {
expect(heir.isObject(50)).toBe(false);
var test = 50;
expect(heir.isObject(test)).toBe(false);
});
it('returns false on strings', function() {
expect(heir.isObject('foo')).toBe(false);
var test = 'foo';
expect(heir.isObject(test)).toBe(false);
});
it('returns false on booleans', function() {
expect(heir.isObject(true)).toBe(false);
var test = true;
expect(heir.isObject(test)).toBe(false);
});
});
describe('heir.merge', function() {
it('copies in values that did not exist', function() {
var chk = heir.merge({foo:true}, {bar: true});
expect(chk).toEqual({foo:true, bar:true});
});
describe('heir.inherit', function () {
it('causes a class to inherit a method', function () {
var Source = function () {};
Source.prototype.foo = function () {};
it('copies in values that did exist', function() {
var chk = heir.merge({foo:true, bar:true}, {foo:false});
expect(chk).toEqual({foo:false, bar:true});
});
var Destination = function () {};
heir.inherit(Destination, Source);
Destination.prototype.bar = function() {};
it('merges objects recursively', function() {
var chk = heir.merge({
nest: {
foo: true,
bar: true
}
}, {
nest: {
bar: false
}
});
var result = new Destination();
expect(chk).toEqual({
nest: {
foo: true,
bar: false
}
});
expect(Destination.prototype.hasOwnProperty('foo')).toBe(false);
expect(Destination.prototype.hasOwnProperty('bar')).toBe(true);
expect(result.foo).toBeDefined();
expect(result.bar).toBeDefined();
});
});
describe('heir.clone', function() {
it('clones objects', function() {
var orig = {
foo: true,
bar: false
it('can have methods overridden', function () {
var Source = function () {};
Source.prototype.foo = function () {
return 'Source#foo';
};
var cl = heir.clone(orig);
var Destination = function () {};
heir.inherit(Destination, Source);
Destination.prototype.foo = function() {
return [
'Destination#foo',
Source.prototype.foo.call(this)
].join(', ');
};
cl.bar = true;
var source = new Source();
var destination = new Destination();
expect(orig).toEqual({
foo: true,
bar: false
});
expect(cl).toEqual({
foo: true,
bar: true
});
expect(source.foo()).toBe('Source#foo');
expect(destination.foo()).toBe('Destination#foo, Source#foo');
});
it('clones objects recursively', function() {
var orig = {
foo: true,
bar: false,
baz: {
one: 100,
two: 300
}
};
it('is correct in the eyes of instanceof', function () {
var Source = function () {};
var Destination = function () {};
heir.inherit(Destination, Source);
var cl = heir.clone(orig);
var source = new Source();
var destination = new Destination();
cl.bar = true;
cl.baz.two = 200;
cl.baz.three = 300;
expect(source instanceof Source).toBe(true);
expect(source instanceof Destination).toBe(false);
expect(orig).toEqual({
foo: true,
bar: false,
baz: {
one: 100,
two: 300
}
});
expect(cl).toEqual({
foo: true,
bar: true,
baz: {
one: 100,
two: 200,
three: 300
}
});
expect(destination instanceof Source).toBe(true);
expect(destination instanceof Destination).toBe(true);
});
});
describe('heir.inherit', function() {
it('inherits a class', function() {
var Base = function(){};
Base.prototype.foo = function() {
return '!foo!';
};
it('has a reference to the parent in this._super', function () {
var Source = function () {};
var Destination = function () {};
heir.inherit(Destination, Source);
var Base2 = function(){};
Base2.prototype.baz = function() {
return '!baz!';
};
var result = new Destination();
var Sub = function(){}.inherit(Base);
Sub.prototype.bar = function() {
return '!bar!';
};
Sub.inherit(Base2);
expect(result._super).toBe(Source.prototype);
});
var b = new Base();
var b2 = new Base2();
var s = new Sub();
it('can have the addition of this._super disabled', function () {
var Source = function () {};
var Destination = function () {};
heir.inherit(Destination, Source, false);
expect(b.bar).not.toBeDefined();
expect(b2.bar).not.toBeDefined();
expect(b.foo()).toEqual('!foo!');
expect(b2.baz()).toEqual('!baz!');
expect(s.foo()).toEqual('!foo!');
expect(s.bar()).toEqual('!bar!');
expect(s.baz()).toEqual('!baz!');
var result = new Destination();
expect(result._super).toBeUndefined();
});
});
it('inherits multiple classes', function() {
var Base = function(){};
Base.prototype.foo = function() {
return '!foo!';
describe('heir.mixin', function () {
it('can mix methods into a class', function () {
var source = {
foo: function () {},
bar: function () {}
};
var Destination = function () {};
heir.mixin(Destination, source);
var result = new Destination();
var Base2 = function(){};
Base2.prototype.baz = function() {
return '!baz!';
};
expect(result.foo).toBeDefined();
expect(result.bar).toBeDefined();
expect(Destination.prototype.hasOwnProperty('foo')).toBe(true);
expect(Destination.prototype.hasOwnProperty('bar')).toBe(true);
});
});
var Sub = function(){}.inherit([Base, Base2]);
Sub.prototype.bar = function() {
return '!bar!';
describe('heir.hasOwn', function () {
it('returns true when it is it\'s own', function () {
var source = {
foo: true
};
var b = new Base();
var b2 = new Base2();
var s = new Sub();
expect(b.bar).not.toBeDefined();
expect(b2.bar).not.toBeDefined();
expect(b.foo()).toEqual('!foo!');
expect(b2.baz()).toEqual('!baz!');
expect(s.foo()).toEqual('!foo!');
expect(s.bar()).toEqual('!bar!');
expect(s.baz()).toEqual('!baz!');
expect(heir.hasOwn(source, 'foo')).toBe(true);
});
it('does not have to be called through the prototype', function() {
var Base = function(){};
Base.prototype.foo = function() {
return '!foo!';
};
it('returns false when it is either undefined or up the prototype chain', function () {
var noProperty = {};
var inChain = heir.createObject({
foo: true
});
var Base2 = function(){};
Base2.prototype.baz = function() {
return '!baz!';
};
expect(heir.hasOwn(noProperty, 'foo')).toBe(false);
expect(inChain.foo).toBeDefined();
expect(heir.hasOwn(inChain, 'foo')).toBe(false);
});
});
var Sub = function(){};
heir.inherit([Base, Base2], Sub);
Sub.prototype.bar = function() {
return '!bar!';
};
describe('heir.merge', function () {
it('merges one object into another', function () {
var a = {foo:true};
var b = {bar:true};
heir.merge(a, b);
var b = new Base();
var b2 = new Base2();
var s = new Sub();
expect(b.bar).not.toBeDefined();
expect(b2.bar).not.toBeDefined();
expect(b.foo()).toEqual('!foo!');
expect(b2.baz()).toEqual('!baz!');
expect(s.foo()).toEqual('!foo!');
expect(s.bar()).toEqual('!bar!');
expect(s.baz()).toEqual('!baz!');
expect(a.foo).toBe(true);
expect(a.bar).toBe(true);
expect(b.foo).toBeUndefined();
});
});
// Run Jasmine
jasmineEnv.execute();
}.call(this));
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc