Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions lib/proto.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,19 @@
* Mixin a given set of properties
* @param prop The properties to mix in
* @param obj [optional]
* @param namesList [optional] Array of names to extend with (if empty all are used)
* The object to add the mixin
*/
mixin: function (prop, obj) {
mixin: function (prop, obj, namesList) {
var self = obj || this;
var fnTest = /\b_super\b/;
var _super = Object.getPrototypeOf(self) || self.prototype;
var descriptors = {};
var proto = prop;
var names = namesList && (Array.isArray(namesList) ? namesList : [namesList]);
var processProperty = function (name) {
if (names && !names.includes(name)) return;

var descriptor = Object.getOwnPropertyDescriptor(proto, name);

if (!descriptors[name] && descriptor) {
Expand Down Expand Up @@ -119,10 +123,11 @@
* Extend the current or a given object with the given property and return the extended object.
* @param prop The properties to extend with
* @param obj [optional] The object to extend from
* @param names [optional] Array of names to extend with (if empty all are used)
* @returns The extended object
*/
extend: function (prop, obj) {
return this.mixin(prop, Object.create(obj || this));
extend: function (prop, obj, names) {
return this.mixin(prop, Object.create(obj || this), names);
},
/**
* Return a callback function with this set to the current or a given context object.
Expand Down
24 changes: 24 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,30 @@ singHello() // Laaaa Laalaaa! Helloooooo!

`proxy` only works on objects extended from UberProto.

### Named extend and mixin
Both `Proto.extend()` and `Proto.mixin()` has an optional third parameter where you can name the methods and symbols you want to extend your object with e.g.:

``` javascript
operaSinger.mixin({
sing : function(text){
return this._super() + ' ' + text;
},
sang : function(text) {
return this.sing() + ' Lolololooo! ' + text;
},
sung : function(text) {
return this.sing() + ' Dodododooo! ' + text;
}
}, undefined, [ 'sang', 'sing' ]);

var singHello = operaSinger.proxy('sing', 'Helloooooo!');
var sangHello = operaSinger.proxy('sang', 'Helloooooo!');

singHello() // Laaaa Laalaaa! Helloooooo!
sangHello() // Laaaa Laalaaa! Lolololooo! Helloooooo!
var sungHello = operaSinger.proxy('sung', 'Helloooooo!'); // results in error
```

## License

MIT License
Expand Down
146 changes: 146 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,4 +265,150 @@ describe('UberProto', function () {
assert.strictEqual(extext.sayHi(), 'Hi David Luecke!!!');
});
});

describe('Named extend and mixin', () => {
it('extends objects with name', function () {
var Original = {
sayHello () {
assert.ok(true, 'sayHello called');
return 'hello';
}
};
var Extended = Proto.extend(Original);
Extended = Extended.extend({
sayHi: function () {
assert.ok(true, 'sayHi called');
return 'hi';
},
sayYo: function () {
assert.ok(true, 'sayYo called');
return 'yo';
}
}, undefined, ['sayHi']);

assert.strictEqual(Extended.create().sayHi(), 'hi', 'Said hi');
assert.strictEqual(Extended.create().sayHello(), 'hello', 'Said hello');
assert.strictEqual(typeof Extended.create().sayYo, 'undefined', 'Cannot Say yo');
});

it('extends objects with names', function () {
var Original = {
sayHello: function () {
assert.ok(true, 'sayHello called');
return 'hello';
}
};
var Extended = Proto.extend(Original);
Extended = Extended.extend({
sayHi: function () {
assert.ok(true, 'sayHi called');
return 'hi';
},
sayYo: function () {
assert.ok(true, 'sayYo called');
return 'yo';
}
}, undefined, ['sayHi', 'sayYo']);

assert.strictEqual(Extended.create().sayHi(), 'hi', 'Said hi');
assert.strictEqual(Extended.create().sayHello(), 'hello', 'Said hello');
assert.strictEqual(Extended.create().sayYo(), 'yo', 'Said yo');
});

it('extends objects with all', function () {
var Original = {
sayHello: function () {
assert.ok(true, 'sayHello called');
return 'hello';
}
};
var Extended = Proto.extend(Original);
Extended = Extended.extend({
sayHi: function () {
assert.ok(true, 'sayHi called');
return 'hi';
},
sayYo: function () {
assert.ok(true, 'sayYo called');
return 'yo';
}
});

assert.strictEqual(Extended.create().sayHi(), 'hi', 'Said hi');
assert.strictEqual(Extended.create().sayHello(), 'hello', 'Said hello');
assert.strictEqual(Extended.create().sayYo(), 'yo', 'Said yo');
});

it('mixin objects with name', function () {
var Original = {
sayHello: function () {
assert.ok(true, 'sayHello called');
return 'hello';
}
};
var Mixined = Proto.mixin(Original);
Mixined = Mixined.mixin({
sayHi: function () {
assert.ok(true, 'sayHi called');
return 'hi';
},
sayYo: function () {
assert.ok(true, 'sayYo called');
return 'yo';
}
}, undefined, ['sayHi']);

assert.strictEqual(Mixined.create().sayHi(), 'hi', 'Said hi');
assert.strictEqual(Mixined.create().sayHello(), 'hello', 'Said hello');
assert.strictEqual(typeof Mixined.create().sayYo, 'undefined', 'Cannot Say yo');
});

it('extends objects with names', function () {
var Original = {
sayHello: function () {
assert.ok(true, 'sayHello called');
return 'hello';
}
};
var Mixined = Proto.mixin(Original);
Mixined = Mixined.mixin({
sayHi: function () {
assert.ok(true, 'sayHi called');
return 'hi';
},
sayYo: function () {
assert.ok(true, 'sayYo called');
return 'yo';
}
}, undefined, ['sayHi', 'sayYo']);

assert.strictEqual(Mixined.create().sayHi(), 'hi', 'Said hi');
assert.strictEqual(Mixined.create().sayHello(), 'hello', 'Said hello');
assert.strictEqual(Mixined.create().sayYo(), 'yo', 'Said yo');
});

it('extends objects with all', function () {
var Original = {
sayHello: function () {
assert.ok(true, 'sayHello called');
return 'hello';
}
};
var Mixined = Proto.mixin(Original);
Mixined = Mixined.mixin({
sayHi: function () {
assert.ok(true, 'sayHi called');
return 'hi';
},
sayYo: function () {
assert.ok(true, 'sayYo called');
return 'yo';
}
});

assert.strictEqual(Mixined.create().sayHi(), 'hi', 'Said hi');
assert.strictEqual(Mixined.create().sayHello(), 'hello', 'Said hello');
assert.strictEqual(Mixined.create().sayYo(), 'yo', 'Said yo');
});
});
});