Created
January 6, 2012 10:16
-
-
Save WebReflection/1569978 to your computer and use it in GitHub Desktop.
proposal to bind once object as callback context pairs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!function (Object) { | |
// (C) WebReflection - Mit Style License | |
var // private scope shortcuts | |
BOUND_TO = "boundTo", // or maybe "asContextOf" ? | |
// ad-hoc partial private shims for "not there yet" ES5 browsers | |
indexOf = [].indexOf || function indexOf(value) { | |
for (var i = this.length; i-- && this[i] !== value;); | |
return i; | |
}, | |
bind = indexOf.bind || function bind(self) { | |
var callback = this; | |
return function bound() { | |
return callback.apply(self, arguments); | |
}; | |
}, | |
defineProperty = Object.defineProperty | |
; | |
// feature detect defineProperty (IE8 inconsistency) | |
try { | |
if (!defineProperty({},"_",{value:1})._) { | |
throw 1; | |
} | |
} catch (o_O) { | |
// in IE8 it will be enumerable, configurable, writable | |
defineProperty = function defineProperty( | |
object, key, descriptor | |
) { | |
object[key] = descriptor.value; | |
}; | |
} | |
// avoid double assignment | |
if (BOUND_TO in Object.prototype) return; | |
defineProperty( | |
Object.prototype, | |
BOUND_TO, { | |
value: function (callback, remove) { | |
// only the very first time | |
// two private stacks are created | |
// and related to the current object | |
// WeakMap behavior emulated | |
var | |
cbStack = [], | |
boundStack = [], | |
self = this | |
; | |
// overwrite the inherited BOUND_TO method | |
// with the one we actually need | |
defineProperty( | |
self, | |
BOUND_TO, { | |
value: function boundTo(callback, remove) { | |
var | |
i = indexOf.call(cbStack, callback), | |
callback = i < 0 ? | |
boundStack[ | |
i = cbStack.push(callback) - 1 | |
] = bind.call(callback, self) | |
: | |
boundStack[i] | |
; | |
// falsy values accepted | |
// except null or undefined | |
// so it's true by default | |
if (remove == false) { | |
cbStack.splice(i, 1); | |
boundStack.splice(i, 1); | |
} | |
// returns bound callback in any case | |
// handy to remove listeners and clean stacks | |
// in one single operation | |
return callback; | |
} | |
} | |
); | |
// only the first time, invoe the overwritten method | |
// use directly latter one every other time | |
return self[BOUND_TO](callback, remove); | |
} | |
} | |
); | |
}(Object); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment